具有派生类列表类型的类属性的 Python 类型注释

标签 python list type-hinting mypy python-typing

对于包含其他派生类的实例列表作为属性的类,键入注释的正确方法是什么。 波纹管是一个“简单”示例,包含两对基类和派生类,我可以在其中重现我无法解决的 mypy 错误。

from dataclasses import dataclass
from typing import List, TypeVar

ClassType = TypeVar("ClassType", bound="BaseClass")


@dataclass
class BaseClass:
    a: int
    b: int


@dataclass
class DerivedClass(BaseClass):
    c: str


@dataclass
class BaseExample:
    list_attr: List[ClassType]  # line 20

    def validate(self, attrs: List[ClassType]) -> List[ClassType]:
        return [attr for attr in attrs if attr.a > 0]


@dataclass
class DerivedExample:
    list_attr: List[ClassType]  # Line 28  # Is actually List[DerivedClass]
    other_attr: int

    def select(self, attrs: List[ClassType]) -> List[ClassType]:
        return [attr for attr in attrs if attr.c] # line 32


ex = DerivedExample(list_attr=[DerivedClass(a=1, b=1, c="text")], other_attr=0)

我收到以下 mypy 错误:

example.py:20: error: Type variable "example.ClassType" is unbound
example.py:20: note: (Hint: Use "Generic[ClassType]" or "Protocol[ClassType]" base class to bind "ClassType" inside a class)
example.py:20: note: (Hint: Use "ClassType" in function signature to bind "ClassType" inside a function)
example.py:28: error: Type variable "example.ClassType" is unbound
example.py:28: note: (Hint: Use "Generic[ClassType]" or "Protocol[ClassType]" base class to bind "ClassType" inside a class)
example.py:28: note: (Hint: Use "ClassType" in function signature to bind "ClassType" inside a function)
example.py:32: error: "ClassType" has no attribute "c"
Found 3 errors in 1 file (checked 1 source file)

mypy==0.942

Python 3.8.6

我在这里使用 TypeVar 是否不正确? 我还尝试按照答案 here 中的建议使用 Generic ,像下面这样定义BaseClass,但它没有解决问题。

ClassType = TypeVar("ClassType", bound="BaseClass")

@dataclass
class BaseClass(Generic[ClassType]):
    a: int
    b: int

我也尝试过不使用 bound 属性,如建议的 in the documentation ,但我遇到了同样的错误。

有没有不同的方法来处理这个结构?

最佳答案

要消除 20 和 28 中的 mypy 错误,您可以使用泛型。但是,您必须使 BaseExample 通用,而不是 BaseClass

@dataclass
class BaseExample(Generic[ClassType]):
    list_attr: List[ClassType]  # line 20

    def validate(self, attrs: List[ClassType]) -> List[ClassType]:
        return [attr for attr in attrs if attr.a > 0]

但是,要消除 32 中的错误,您必须定义一个由 DerivedClass 绑定(bind)的新类型 var。为什么?因为属性cBaseClass中不可用,但在DerivedClass中引入。因此,将 BaseClassDerivedExample 一起使用永远不会起作用。

ClassType2 = TypeVar("ClassType2", bound="DerivedClass")
@dataclass
class DerivedExample(Generic[ClassType2]):
    list_attr: List[ClassType2]  # Line 28  # Is actually List[DerivedClass]
    other_attr: int

    def select(self, attrs: List[ClassType2]) -> List[ClassType2]:
        return [attr for attr in attrs if attr.c] # line 32

你可以试试here .

关于具有派生类列表类型的类属性的 Python 类型注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73574294/

相关文章:

python - 有没有办法通过 pip install 运行 2to3?

python - 添加列表中的内容

c - 在 malloc 实现中维护空闲列表

python - 参数化泛型不能与类或实例检查一起使用

python - 如何键入提示函数局部范围内定义的返回值?

python - 区分类型别名和实际类的约定?

python - 检查元素在 Selenium 中是否可点击

python - 根据另一个文件中保存的列表选择文件中的变量

python - 给定两个元组列表找到它们之间最近的元组(dist

Sharepoint ListView 设置