No puedo entender el uso de Generic y TypeVar , y cómo están relacionados. https://docs.python.org/3/library/typing.html#building-generic-types
Los documentos tienen este ejemplo:
class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc. X = TypeVar('X') Y = TypeVar('Y') def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y: try: return mapping[key] except KeyError: return defaultLas variables de tipo existen principalmente para el beneficio de los verificadores de tipos estáticos. Sirven como parámetros para tipos genéricos, así como para definiciones de funciones genéricas.
¿Qué no puedo simplemente usar Mapping con algún tipo existente, como int , en lugar de crear X e Y ?
El propósito general de usar X e Y es cuando uno quiere que los parámetros sean lo más genéricos posible. en su lugar, se puede usar int . La diferencia es: el analizador estático interpretará el parámetro como siempre un int . Usar X e Y significa que la función acepta cualquier tipo de parámetro. El analizador estático, como en un IDE, por ejemplo, determinará el tipo de X e Y y, por lo tanto, el tipo de devolución, ya que los argumentos de tipo X e Y se proporcionan en la llamada a la función.
mapping: Mapping[str, int] = {"2": 2, "3": 3} name = lookup_name(mapping, "1", 1) En el ejemplo anterior, los verificadores de tipos sabrán que el name siempre será un int dependiendo de las anotaciones de tipo. En los IDE, se mostrará la finalización del código para los métodos int .
Usar tipos específicos es lo ideal si ese es tu objetivo. La función que acepta solo un mapa con claves o valores int y/o devuelve int .
Puede cambiar X e Y a cualquier tipo que desee, básicamente. Ese es un ejemplo amplio.
El siguiente ejemplo es posible:
def lookup_name(mapping: Mapping[str, int], key: str, default: int) -> int: try: return mapping[key] except KeyError: return defaultLos tipos no son genéricos en el ejemplo anterior. La clave siempre será str; el valor, el valor por defecto y el tipo de retorno siempre será un int. Es la elección del programador. Sin embargo, Python no aplica esto. Para eso se necesita un verificador de tipo estático como mypy .
Como explica @mistermiyagi, X e Y son básicamente variables que representan tipos en Python.
El tipo Genérico podría incluso estar restringido si se desea:
import typing X = typing.TypeVar("X", int, str) Y = typing.TypeVar("Y", int)