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

问题描述 投票:0回答:1

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

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
属性,如文档中所建议的那样,但我得到了相同的错误。

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

python mypy python-typing
1个回答
3
投票
要消除 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

 绑定的新类型 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
您可以在这里

尝试一下。

© www.soinside.com 2019 - 2024. All rights reserved.