mypy:包含不同子类实例的字典
mypy: Dict containing instances of different subclasses
在下面的代码示例中,我们有一个包含抽象基础实例 class 及其子类型实例的字典。
from typing import Dict, Union
class Base:
def __init__(self):
self.x = 0
class Sub(Base):
def __init__(self):
super().__init__()
self.y = 1
d: Dict[str, Base] = {
'base': Base(),
'sub': Sub()
}
print(d['sub'].y)
访问子类型的实例变量导致 Pycharm 中的 linter 警告 Unresolved attribute reference 'y' for class 'Base'
。
使用 mypy 检查此示例会引发错误:
error: Item "Base" of "Union[Base, Sub]" has no attribute "y"
将代码更改为
d: Dict[str, Union[Base, Sub]] = {
'base': Base(),
'sub': Sub()
}
修复了 Pycharm 中的 linter 警告,但在 mypy 中仍然出现错误。
从mypy docs我知道"most mutable generic collections are invariant"。因此我假设 dict
是 "invariant"?
这是否意味着在 mypy 中不可能有一个包含不同子 classes 实例的字典?如果是这样,是否可以以某种方式更改此代码以使其通过 mypy?
由于密钥在运行前是未知的,我假设 TypedDict
不是一个选项?
从值访问一个字段,而它的类型可以是没有该字段的类型(Base
在您的情况下)——从 mypy
的角度(以及我的角度)来看,这是一个错误。
您应该重新考虑您的 类 和继承层次结构,或者添加 isinstance
检查
... # same as before
value = d['sub']
if isinstance(value, Sub):
print(value.y)
和mypy
会说出类似
的内容
Success: no issues found in 1 source file
您可以使用 cast
告诉 mypy
是的,您承诺 d['sub']
将是 Sub
的实例(不仅仅是 [= 的未指定子类) 15=]),它将具有 y
属性。
print(typing.cast(Sub, d['sub']).y)
在下面的代码示例中,我们有一个包含抽象基础实例 class 及其子类型实例的字典。
from typing import Dict, Union
class Base:
def __init__(self):
self.x = 0
class Sub(Base):
def __init__(self):
super().__init__()
self.y = 1
d: Dict[str, Base] = {
'base': Base(),
'sub': Sub()
}
print(d['sub'].y)
访问子类型的实例变量导致 Pycharm 中的 linter 警告 Unresolved attribute reference 'y' for class 'Base'
。
使用 mypy 检查此示例会引发错误:
error: Item "Base" of "Union[Base, Sub]" has no attribute "y"
将代码更改为
d: Dict[str, Union[Base, Sub]] = {
'base': Base(),
'sub': Sub()
}
修复了 Pycharm 中的 linter 警告,但在 mypy 中仍然出现错误。
从mypy docs我知道"most mutable generic collections are invariant"。因此我假设 dict
是 "invariant"?
这是否意味着在 mypy 中不可能有一个包含不同子 classes 实例的字典?如果是这样,是否可以以某种方式更改此代码以使其通过 mypy?
由于密钥在运行前是未知的,我假设 TypedDict
不是一个选项?
从值访问一个字段,而它的类型可以是没有该字段的类型(Base
在您的情况下)——从 mypy
的角度(以及我的角度)来看,这是一个错误。
您应该重新考虑您的 类 和继承层次结构,或者添加 isinstance
检查
... # same as before
value = d['sub']
if isinstance(value, Sub):
print(value.y)
和mypy
会说出类似
Success: no issues found in 1 source file
您可以使用 cast
告诉 mypy
是的,您承诺 d['sub']
将是 Sub
的实例(不仅仅是 [= 的未指定子类) 15=]),它将具有 y
属性。
print(typing.cast(Sub, d['sub']).y)