python - 如何使用同时支持简单类型和属性的字段声明协议?
问题描述
(相关,但不重复:How to annotate that can be implemented as property?)
我想创建一个Protocol
,其中一个字段可以通过简单的类型和属性来实现。例如:
class P(Protocol):
v: int
@dataclass
class Foo(P):
v: int
class Bar(P):
@property
def v(self) -> int: # ERROR
return
但是上面的代码没有类型检查。我应该如何解决它?
注意:我想在不重写Foo
and的情况下解决这个问题Bar
,因为Foo
andBar
不是我实现的。
根据这个问题,下面的代码不是解决方案,因为只读property
和简单成员的语义略有不同。
class P(Protocol):
@property
def v(self) -> int: # declare as property
...
Protocol
由于差异,Pyright 否认了这一点。
解决方案
通常,声明Protocol
使用只读property
字段,而不是读/写字段:
class P(Protocol):
@property
def v(self) -> int:
pass
这是必需的,因为只读和读/写字段都满足只读协议属性。相反,读/写协议属性仅由读/写字段满足,而不是只读字段。property
property
由于 PyRight 坚持字段和属性是不同类型的属性,因此必须使用两种变体声明属性——一次作为字段,一次作为属性。对于简单的协议,这可以通过声明属性的单独字段和属性变体来完成:
# field only
class Pf(Protocol):
v: int
# property only
class Pp(Protocol):
@property
def v(self) -> int:
return 1
# Either field or property
P = Union[Pf, Pp]
这对 MyPy 和 PyRight 都有效。
推荐阅读
- java - 类中的这些字段有什么区别
- mysql - 在迁移中使用我的 schema.rb 时,我收到关于 ID 字段的错误
- matrix - IML 的替代品?在没有 IML 的情况下运行 SAS Viya,需要合并两个非嵌套集群的协方差矩阵
- react-native - 为什么响应类型不同?
- pokeapi - PokeAPI:有没有办法请求规范化数据而不是嵌套 json?
- javascript - 如何根据当前状态值使单选按钮选中/激活
- flutter - 重构问题:提取为小部件/方法/变量......有什么优点和缺点?
- python - Telegram-python-Bot 使用 callback_query 获取用户文本输入
- xamarin - 将 CarouselPage 转换为 CarouselView
- mongodb - Mongo db 4.2:将数组项的字段替换为匹配文档的另一个字段的值