mypy:如何在泛型类中声明返回 self 的方法的返回类型?

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

这个答案似乎不适用于仿制药。在检查以下代码时,Mypy 抱怨“错误:缺少泛型类型 A 的类型参数”。我尝试使用

'A[T]'
作为 TypeVar,但 mypy 说“错误:类型变量 T 未绑定。”我还尝试使用
AnyA[T]
作为
get
的返回类型,但这会产生两个错误消息,已知的“错误:缺少泛型类型 A 的类型参数”和新的错误消息“与参数一起使用的类型变量 AnyA”。

如何正确指定

get
的返回类型?

import typing

T = typing.TypeVar('T')
AnyA = typing.TypeVar('AnyA', bound='A')

class A(typing.Generic[T]):

    def __init__(self, val: T) -> None:
        self.val = val

    def get(self: AnyA) -> AnyA:
        return self

class B(A[T]):
    def is_int(self) -> bool:
        return isinstance(self.val, int)


if __name__ == '__main__':
    b = B(42)
    print(b.get().is_int())
python generics mypy python-typing
1个回答
9
投票

我知道在这里打字的三种方式:

宣告内心的自我类型

此方法在

mypy
文档中进行了描述,请参阅替代构造函数的精确类型

class A(typing.Generic[T]):
    _Self = typing.TypeVar('_Self', bound='A[T]')

    def __init__(self, val: T) -> None:
        self.val = val

    def get(self: _Self) -> _Self:
        return self

但请注意,这是

mypy
特定的内容,可能无法与其他检查器一起使用。例如。
pyre
尚不支持内在自我类型。

使用
_typeshed.Self

这节省了声明自定义类型的样板,但需要从 typeshed 进行一些模糊的导入,这在运行时会失败。因此它必须被

typing.TYPE_CHECKING
:

包裹
from typing import Any, TYPE_CHECKING

if TYPE_CHECKING:
    from _typeshed import Self
else:
    Self = Any

class A(typing.Generic[T]):
    def __init__(self, val: T) -> None:
        self.val = val

    def get(self: Self) -> Self:
        return self

_typeshed.Self
最初是为了在自定义存根中使用而创建的,但也适用于内联类型。

Python 3.11 及更高版本:
typing.Self

最近推出的 PEP 673

Self
添加到 stdlib,因此从 Python 3.11 开始,人们将能够使用它:

from typing import Self

class A(typing.Generic[T]):
    def __init__(self, val: T) -> None:
        self.val = val

    def get(self: Self) -> Self:
        return self

到目前为止,

mypy
尚不支持这一点,但例如由 1.1.184 版本中的
pyright
提供。

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