Executando o código abaixo com 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])
Isso lançará um 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
Qual foi a razão para o Python não permitir isinstance
verificações com Generic
s?
Em tempo de execução, os argumentos de tipo não são verificáveis. Tais relacionamentos são verificados apenas no momento da verificação de tipo:
Por exemplo, se
isinstance(..., list[str])
fosse tratado emisintansce(..., list)
, o resultado seria muito confuso:Considere também o caso em que os argumentos de tipo não são concretos:
Este sempre foi o caso desde o PEP 484, embora não muito explicitamente ( Callable e Generics são duas seções diferentes, e esta nota parece significar algo um pouco diferente do que consideramos, embora conceitualmente o mesmo):
No entanto, existem verificadores de tipo de tempo de execução que fazem esse tipo de trabalho pesado, como o Pydantic.
Historicamente, a nota PEP 484 foi adicionada neste commit , e problemas relacionados ao apagamento de tipo foram discutidos nesta edição do GitHub . Parece que o GvR e outros contribuidores inicialmente se opuseram
Node[int]()
(que funcionava em tempo de execução, mas muito lento, e foi proibido pelo Mypy) devido a problemas de desempenho.