使用 Python 3.12.4 运行以下代码:
from typing import Generic, TypeVar
T = TypeVar("T")
class Foo(Generic[T]):
def some_method(self) -> T:
pass
isinstance(Foo[int](), Foo[int])
它将抛出一个TypeError: Subscripted generics cannot be used with class and instance checks
。
Traceback (most recent call last):
File "/path/to/a.py", line 9, in <module>
isinstance(Foo[int](), Foo[int])
File "/path/to/.pyenv/versions/3.12.4/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/typing.py", line 1213, in __instancecheck__
return self.__subclasscheck__(type(obj))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/.pyenv/versions/3.12.4/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/typing.py", line 1216, in __subclasscheck__
raise TypeError("Subscripted generics cannot be used with"
TypeError: Subscripted generics cannot be used with class and instance checks
isinstance
Python 不允许使用 s 进行检查的理由是什么Generic
?
在运行时,类型参数是不可验证的。此类关系仅在类型检查时进行检查:
例如,如果
isinstance(..., list[str])
在 时进行处理isintansce(..., list)
,结果将会非常令人困惑:还请考虑类型参数不具体的情况:
自 PEP 484 以来,情况一直如此,尽管不是非常明确( Callable和Generics是两个不同的部分,并且此注释的含义似乎与我们所认为的略有不同,尽管概念上是相同的):
但是,有一些运行时类型检查器可以完成这种繁重的工作,例如 Pydantic。
历史上,PEP 484 注释被添加到了此提交中,并且类型擦除相关问题已在此 GitHub 问题中讨论。看来 GvR 和其他贡献者最初反对该功能
Node[int]()
(它在运行时可以运行但速度非常慢,并被 Mypy 禁止),原因是存在性能问题。