Anotaciones que describen, no imponen
Un type hint es una nota que pegas a un nombre — normalmente un parámetro de función — diciendo "esto debería ser un int", "esto devuelve una lista de strings", y así. Python no los comprueba en tiempo de ejecución. Pasar un string donde anotaste un int no lanza un error. Tu editor y herramientas externas (mypy, pyright, Pylance vía VS Code) leen las hints y te avisan antes de que el código se ejecute.
El caso más simple posible:
name: str anota el parámetro. -> str anota el valor de retorno. Ambas llamadas se ejecutan. La segunda está mal — un type checker estático la marcaría — pero Python en sí la procesa alegremente porque 42 resulta que soporta la interpolación f"{...}".
Ese es el modelo mental crucial: las hints son documentación que una máquina puede leer. No cambian el runtime.
¿Por qué molestarse?
Tres victorias concretas, en orden de cuánto tardan en pagarse:
- Tu editor se vuelve más listo. El autocompletado muestra los métodos correctos, los renombres se propagan correctamente y pasar el cursor sobre una variable te dice su tipo.
- Las firmas de función se autodescriben.
def fetch(url: str, timeout: float = 5.0) -> dict:le dice a un lector exactamente qué pasar y qué va a recibir — sin necesidad de leer el cuerpo. - Los type checkers cazan errores antes de que ejecutes el código. Ejecutar
mypy .en un proyecto saca a la luz el tipo de bugs que los tests unitarios suelen perder —Nonedevuelto donde esperabas un valor, un dict usado donde encaja una lista.
Para un script de un solo archivo que solo tú, solo hoy, sáltate las hints. Para cualquier cosa a la que vas a volver o que vas a compartir, los quince segundos que tardan en escribirse se pagan en una hora.
Tipos incorporados básicos
No necesitas un import para ninguno de estos:
Las anotaciones de variable (name: str = "Rosa") raramente son necesarias — Python infiere el tipo del lado derecho. Resérvalas para parámetros, tipos de retorno y el caso ocasional donde el tipo inferido sea ambiguo.
Las funciones que no devuelven nada usan -> None:
Listas, dicts, tuplas y sets
Los contenedores necesitan un segundo dato — qué contienen. Python moderno te deja subscribir los tipos incorporados directamente:
Leyéndolas en voz alta:
list[float]— una lista de floats.dict[str, int]— un dict con claves string y valores int.tuple[float, float]— una tupla de exactamente dos floats.set[str]— un set de strings.
La sintaxis de subscripción list[...], dict[...] funciona en Python 3.9 y posteriores. En código más antiguo verás List, Dict, Tuple importados de typing — mismo significado, escritura más antigua.
Valores opcionales
"Puede ser None" es común. Tiene dos escrituras equivalentes — ambas están bien, pero la más nueva se lee mejor:
str | None significa "un string, o None". La sintaxis | funciona en Python 3.10+. En código más antiguo verás Optional[str] del módulo typing, que significa lo mismo.
Quien llame y vea -> str | None sabe que debe comprobar None antes de usar el resultado — ese es el punto entero de la anotación.
Tipos Union: esto o aquello
Cuando un valor podría ser uno de varios tipos, usa |:
Puedes unir más de dos tipos. int | str | float significa "cualquiera de estos tres".
Anotar variables dentro de funciones
La mayor parte del tiempo Python puede averiguar el tipo de una variable local desde su inicializador. Solo necesitas una anotación cuando:
- El contenedor empieza vacío y el type checker no puede adivinar su contenido.
- El valor podría ser de varios tipos y quieres comprometerte con uno.
- Quieres documentar la intención para un lector humano.
typing.Any es la escotilla de escape — "no quiero anotar esto de forma precisa". Úsalo con moderación. Abusar de Any hace el resto de tus type hints sin valor.
Anotar clases
Los atributos de clase y las firmas de método se anotan de la misma forma que cualquier otra función:
Los dataclasses sí que requieren anotaciones de tipo — el decorador @dataclass las lee para generar __init__ y __repr__. Ese es el único sitio donde las anotaciones afectan al comportamiento en runtime.
Tuplas y el caso "cualquier longitud"
tuple[...] tiene dos formas que confunden a los novatos:
tuple[float, float]— exactamente dos floats.tuple[int, ...]— cualquier número de ints. El...(un elemento de sintaxis real en el sistema de tipos) significa "y así".
Callables y aliases de tipo
Cuando una función toma o devuelve otra función, usa Callable:
Callable[[int], int] significa "una función que toma un int y devuelve un int".
Cuando una anotación se vuelve repetitiva, ponle nombre:
Un alias es simplemente una asignación normal de Python. En cualquier sitio donde usarías la forma larga, el nombre corto funciona.
Ejecutar un type checker
El propio intérprete de Python ignora los type hints. Para comprobarlos de verdad, instala un type checker. mypy es el original; pyright (usado por Pylance de VS Code) es más rápido.
pip install mypy
mypy your_project/
La primera ejecución saca a la luz errores en sitios que no habías notado. Trabaja a través de ellos incrementalmente — # type: ignore silencia una sola línea cuando necesites seguir adelante.
Los IDEs modernos ejecutan la verificación de tipos continuamente mientras editas, así que la mayor parte del feedback llega antes de que guardes.
Cuándo los type hints no encajan
- Scripts exploratorios rápidos. Las anotaciones añaden fricción a código que vive una hora.
- Código muy dinámico. La metaprogramación, los sistemas de plugins y patrones similares a menudo crecen más allá de lo que puede describir el sistema de tipos. Anota la API externa y deja las entrañas sueltas.
- Librerías de terceros sin tipos. Si una librería que importas no tiene información de tipos,
Anyse filtra en tu código. Está bien — no es código tuyo para anotar.
Para todo lo demás, los type hints son un hábito pequeño con una gran recompensa. El coste son unas pocas pulsaciones extra por firma de función. El retorno son menos bugs, refactors más fáciles y código que se documenta a sí mismo.
Siguiente: módulos e imports
Ya tienes todo el tooling a nivel de función — argumentos, decoradores, type hints. A continuación veremos cómo organiza Python el código entre archivos: módulos, paquetes y el sistema de imports.
Preguntas frecuentes
¿Qué son los type hints en Python?
Los type hints son anotaciones que describen los tipos esperados de variables, parámetros de función y valores de retorno. Python en sí no los impone en tiempo de ejecución — son para herramientas (IDEs, linters, type checkers como mypy o pyright) y para humanos leyendo el código.
¿Los type hints hacen que Python corra más rápido?
No. El intérprete de Python ignora los type hints en tiempo de ejecución. La mejora está en tu bucle de desarrollo — menos typos que cazan los editores, firmas de función más claras, refactors más seguros.
¿Cuándo debería añadir type hints?
Añádelos a firmas de funciones públicas — parámetros y tipos de retorno. Añádelos con moderación dentro de los cuerpos de función, solo donde el tipo de una variable no sea obvio. Para scripts de una sola vez, son opcionales. Para código compartido y librerías, se pagan solos rápido.