对于包含其他派生类的实例列表作为属性的类,键入注释的正确方法是什么。
波纹管是一个“简单”示例,包含两对基类和派生类,我可以在其中重现我无法解决的 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。为什么?因为属性c
在BaseClass
中不可用,但在DerivedClass
中引入。因此,将 BaseClass
与 DerivedExample
一起使用永远不会起作用。
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/