mypy:如何在泛型 class 中声明 return 方法的 return 类型?
mypy: How to declare the return type of a method returning self in a generic class?
似乎不适用于泛型。 Mypy 在检查以下代码时抱怨“错误:缺少泛型类型 A 的类型参数”。我曾尝试对 TypeVar 使用 'A[T]'
,但随后 mypy 显示“错误:类型变量 T 未绑定。”我也尝试过使用 AnyA[T]
作为 return 类型的 get
但这会产生两条错误消息,即已知的“错误:通用类型 A 缺少类型参数”和新的错误消息“与参数一起使用的类型变量 AnyA".
如何正确指定 get
的 return 类型?
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())
我知道这里有三种输入方式:
正在声明一个内部 self-type
此方法在 mypy
文档中进行了描述,请参阅 Precise typing of alternative constructors。
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
尚不支持内部 self-types。
使用_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
。
'A[T]'
,但随后 mypy 显示“错误:类型变量 T 未绑定。”我也尝试过使用 AnyA[T]
作为 return 类型的 get
但这会产生两条错误消息,即已知的“错误:通用类型 A 缺少类型参数”和新的错误消息“与参数一起使用的类型变量 AnyA".
如何正确指定 get
的 return 类型?
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())
我知道这里有三种输入方式:
正在声明一个内部 self-type
此方法在 mypy
文档中进行了描述,请参阅 Precise typing of alternative constructors。
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
尚不支持内部 self-types。
使用_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
。