在 python 中,我可以缩小 class 的协议定义属性吗?
In python, can I narrow down protocol-defined properties of the class?
让我用一个例子来解释:
import typing as t
from dataclasses import dataclass
# describe our protocols
class ID(t.Protocol):
"This protocol describes some kind of ID."
def __hash__(self) -> int:
raise NotImplementedError
def __eq__(self, other) -> bool:
raise NotImplementedError
def __str__(self) -> str:
raise NotImplementedError
class ObjectWithID(t.Protocol):
"This protocol describes an object that has an ID."
@property
def id(self) -> ID:
raise NotImplementedError
# now describe real classes
class MyID(ID):
"Implementation of ID protocol"
def __init__(self, val: int):
self.value: int = val
def __hash__(self) -> int:
return self.value
def __eq__(self, other) -> bool:
return isinstance(other, MyID) and self.value == other.value
def __str__(self) -> str:
return str(self.value)
@dataclass
class MyObject(ObjectWithID):
id: MyID # <<< THIS
现在,PyCharm 坚持认为 id 是 MyID 类型破坏了与 ObjectWithID 协议的兼容性。
然而,pylint 并不介意这一行。
我也不,因为从我的角度来看,任何正确的 MyObject 实例都将与 ObjectWithID 协议兼容。
谁是正确的?只抑制 PyCharm 中的警告对我来说安全吗?
我可以看到,如果存在 ID 的另一个实现,MyObject 将不会接受它,而 ObjectWithID 可以。但这真的是个问题吗?
由于MyID
继承自ID
,我认为pycharm
是错误的,pylint
是正确的。
mypy
在其文档中说明了以下关于子类的内容:
Any instance of a subclass is also compatible with all superclasses
见https://mypy.readthedocs.io/en/stable/kinds_of_types.html#class-types
让我用一个例子来解释:
import typing as t
from dataclasses import dataclass
# describe our protocols
class ID(t.Protocol):
"This protocol describes some kind of ID."
def __hash__(self) -> int:
raise NotImplementedError
def __eq__(self, other) -> bool:
raise NotImplementedError
def __str__(self) -> str:
raise NotImplementedError
class ObjectWithID(t.Protocol):
"This protocol describes an object that has an ID."
@property
def id(self) -> ID:
raise NotImplementedError
# now describe real classes
class MyID(ID):
"Implementation of ID protocol"
def __init__(self, val: int):
self.value: int = val
def __hash__(self) -> int:
return self.value
def __eq__(self, other) -> bool:
return isinstance(other, MyID) and self.value == other.value
def __str__(self) -> str:
return str(self.value)
@dataclass
class MyObject(ObjectWithID):
id: MyID # <<< THIS
现在,PyCharm 坚持认为 id 是 MyID 类型破坏了与 ObjectWithID 协议的兼容性。 然而,pylint 并不介意这一行。 我也不,因为从我的角度来看,任何正确的 MyObject 实例都将与 ObjectWithID 协议兼容。
谁是正确的?只抑制 PyCharm 中的警告对我来说安全吗?
我可以看到,如果存在 ID 的另一个实现,MyObject 将不会接受它,而 ObjectWithID 可以。但这真的是个问题吗?
由于MyID
继承自ID
,我认为pycharm
是错误的,pylint
是正确的。
mypy
在其文档中说明了以下关于子类的内容:
Any instance of a subclass is also compatible with all superclasses
见https://mypy.readthedocs.io/en/stable/kinds_of_types.html#class-types