我正在尝试创建一个类,该类的属性应该是常量。该属性可以有不同的类型,具体取决于代码库中是否使用了该类。此外,该属性的类型在整个类中的各种类型提示中使用¹,因此我决定将该类转换为 Generic
,如下所示:
from typing import TypeVar, Generic, Final
T = TypeVar("T")
class Foo(Generic[T]):
bar: Final[T]
def __init__(self, bar: T) -> None:
self.bar = bar
但是,MyPy 提示说
Final name declared in class body cannot depend on type variables
如果我删除 Final
注释,MyPy 不会引发任何错误。
我在我的代码中找不到任何逻辑错误:它只是说,无论其类型如何,bar
属性都应始终引用同一对象。我是否遗漏了什么或者这是 Python 和/或 MyPy 的某些限制?
¹在示例中,为了简单起见,我只展示了一种此类用法。
附言我使用的是 Python 3.10.8 和 MyPy 0.991。
最佳答案
根据 PEP591,您的代码是正确的,mypy
以错误的顺序应用规则,在 __init__
中注释以解决问题。
mypy
应该检查初始化程序是否存在,然后确定是否缺少初始化程序,但实际上并没有,并且认为您定义了一个最终的类属性,尽管缺少初始化程序。类型变量在类属性的类型中没有意义(因为类型变量绑定(bind)到实例,而不是类),所以 mypy
在这里出错。
因此我们需要帮助mypy
正确解析Final
的类型。为此,我们可以在 __init__
中注释属性:
from typing import TypeVar, Generic, Final
_T = TypeVar("_T")
class Foo(Generic[_T]):
def __init__(self, bar: _T):
self.bar: Final[_T] = bar
现在进行类型检查 ( playground )。
关于python - MyPy 不允许将通用属性标记为最终属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75158767/