python - MyPy 不允许将通用属性标记为最终属性

标签 python mypy python-typing

我正在尝试创建一个类,该类的属性应该是常量。该属性可以有不同的类型,具体取决于代码库中是否使用了该类。此外,该属性的类型在整个类中的各种类型提示中使用¹,因此我决定将该类转换为 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__ 中注释以解决问题。

这里是 the docs 的链接和 PEP591 .

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/

相关文章:

python - 如何替换数据框中的索引

python - Flask:无法让gunicorn 将所有内容记录到文件中

python - 如何让Mypy按预期处理函数中的子类

python - Polars API 注册和类型检查器

python - 类型 - 函数返回值类型与表达式的类型相同

python - 使用 scikit-learn 和 pandas 编写对中断具有鲁棒性的结果表

Python键绑定(bind)/捕获

Python 泛型和子类

python-3.x - 向重写的函数添加额外的参数,而不会出现 pylint 提示

python - 如何输入带有任意参数列表(vararg)的可调用函数