【发布时间】:2021-10-09 11:42:50
【问题描述】:
假设我有一个基类
from typing import List, Optional
class Node:
def __init__(self, name: str) -> None:
self.name = name
self.children: List['Node'] = []
...
和一个子类
class PropertiesNode(Node):
def __init__(self, name: str, properties: List[str], inherit: Optional['PropertiesNode']) -> None:
Node.__init__(self, name)
self.properties = set(properties)
if inherit:
self.properties.update(inherit.properties)
self.children = deepcopy(inherit.children)
for child in self.children:
child.properties.update(properties) # ERR: "Node" has no attribute "properties" [attr-defined]
如您所见,mypy(正确地)在那里标记了一个错误,因为Node.children 被明确地赋予了List[Node] 的类型。
所以我阅读了泛型类型,在我看来解决方案是使用TypeVars 和Generic:
from typing import Generic, List, Optional, TypeVar
N = TypeVar('N', bound='Node')
P = TypeVar('P', bound='PropertiesNode')
class Node(Generic[N]):
def __init__(self: N, name: str) -> None:
self.name = name
self.children: List[N] = []
class PropertiesNode(Node[P]):
def __init__(self: P, name: str, properties: List[str], inherit: Optional[P]) -> None:
Node.__init__(self, name)
self.properties = set(properties)
if inherit:
self.properties.update(inherit.properties)
self.children = deepcopy(inherit.children)
for child in self.children:
child.properties.update(properties)
但是,现在当我实例化类时,我得到了
foo = Node("foo") # ERR Need type annotation for "foo" [var-annotated]
bar = PropertiesNode("bar", ["big", "green"], None) # ERR Need type annotation for "bar" [var-annotated]
现在,我可以通过这样做来使这些静音
foo: Node = Node("foo")
bar: PropertiesNode = PropertiesNode(...)
但是为什么它会沉默 - 我没有在那里给 mypy 任何新信息?我想得越多,Generic 似乎就越少,因为问题是:Node 或PropertiesNode 的所有实例都将具有与self 完全相同类型的self.children。
但如果我从class Node(Generic[N]): 中删除Generic[N],我最终会再次出现原始错误:
class PropertiesNode(Node):
...
child.properties.update(properties) # ERR "N" has no attribute "properties" [attr-defined]
【问题讨论】:
标签: python generics type-hinting mypy python-typing