mypy:包含不同子类实例的Dict

2024-04-26 13:32:03 发布

您现在位置:Python中文网/ 问答频道 /正文

在下面的代码示例中,我们有一个包含抽象基类实例及其子类型实例的dict。你知道吗

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我知道“大多数可变的泛型集合是不变的”。因此,我假设dict是“不变的”?你知道吗

这是否意味着在mypy中不可能有一个包含不同子类实例的dict?如果是这样的话,这个代码是否可以被修改以通过mypy?你知道吗

由于密钥在运行之前是未知的,我假设TypedDict不是一个选项?你知道吗


Tags: 实例代码self示例类型baseinitdef
2条回答

您可以使用cast告诉mypy,是的,您承诺d['sub']将是Sub(而不仅仅是Base的未指定子类)的实例,它将具有y属性。你知道吗

print(typing.cast(Sub, d['sub']).y)

从值访问一个字段,当它的类型可以是没有该字段的类型时(在您的例子中是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

相关问题 更多 >