Python Type Hints: Código Más Seguro y Claro
Probablemente te hayas encontrado con una función de Python que devuelve diferentes tipos según la entrada, o una variable que cambia de tipo a mitad de camino. Estas ambigüedades provocan errores en tiempo de ejecución que podrían haberse detectado antes. Los type hints de Python resuelven esto al permitirte anotar los tipos esperados, haciendo tu código autodocumentado y permitiendo que herramientas de análisis estático detecten errores antes de la ejecución.
En este artículo, exploraremos cómo usar eficazmente los type hints en Python, desde anotaciones básicas hasta patrones avanzados, y cómo contribuyen a un código más seguro y claro.
¿Qué son los type hints de Python?
Los type hints (también llamados anotaciones de tipo) son una sintaxis introducida en Python 3.5 (PEP 484) que te permite especificar los tipos esperados de variables, parámetros de funciones y valores de retorno. No se aplican en tiempo de ejecución, pero son utilizados por verificadores de tipos estáticos como mypy, pyright y los IDE para detectar errores relacionados con tipos.
Por ejemplo:
def greet(name: str) -> str:
return f"Hello, {name}"
Aquí, name: str indica que name debería ser una cadena, y -> str indica que la función devuelve una cadena.
¿Por qué usar type hints?
- Detección temprana de errores: Los verificadores de tipos estáticos pueden detectar discrepancias de tipos antes de que ejecutes el código.
- Mejor legibilidad: Los type hints sirven como documentación en línea, facilitando que otros (y tu yo futuro) entiendan el código.
- Mejor soporte del IDE: El autocompletado, la refactorización y la navegación se vuelven más precisos.
- Mayor mantenibilidad: Al refactorizar, los type hints ayudan a asegurar que no rompas contratos.
- Facilita la colaboración: Los equipos pueden comunicar claramente las interfaces esperadas.
Anotaciones de tipo básicas
Puedes anotar variables, parámetros de funciones y tipos de retorno.
Variables
age: int = 30
name: str = "Alice"
Funciones
def add(a: int, b: int) -> int:
return a + b
Colecciones
Para listas, diccionarios, etc., usa el módulo typing (o los genéricos integrados en Python 3.9+):
from typing import List, Dict
def process(items: List[str]) -> Dict[str, int]:
return {item: len(item) for item in items}
En Python 3.9+, puedes usar list[str] y dict[str, int] directamente.
Type hints avanzados
A medida que tu código crece, te encontrarás con escenarios más complejos. Aquí hay algunas características avanzadas.
Optional y Union
Optional[T] es una abreviatura de Union[T, None], que indica un valor que puede ser de tipo T o None.
from typing import Optional
def find_user(user_id: int) -> Optional[str]:
# returns username or None if not found
...
En Python 3.10+, puedes usar el operador |: str | None.
Callable
Para funciones como argumentos:
from typing import Callable
def apply_func(func: Callable[[int], int], value: int) -> int:
return func(value)
Genéricos
Crea componentes reutilizables con variables de tipo:
from typing import TypeVar, List
T = TypeVar('T')
def first(items: List[T]) -> T:
return items[0]
TypedDict
Para diccionarios con un conjunto fijo de claves y tipos de valores:
from typing import TypedDict
class User(TypedDict):
name: str
age: int
def greet(user: User) -> str:
return f"Hello, {user['name']}"
Usando verificadores de tipos estáticos
Los type hints solo son útiles si los verificas. Las herramientas populares incluyen mypy, pyright y pyre. Veamos cómo usar mypy.
- Instala mypy:
pip install mypy - Ejecútalo en tu código:
mypy your_script.py - Corrige los errores reportados.
Por ejemplo, dado:
def add(a: int, b: int) -> int:
return a + b
add("1", "2")
mypy reportará: error: Argument 1 to "add" has incompatible type "str"; expected "int".
Puedes configurar mypy mediante un archivo mypy.ini o pyproject.toml para aplicar verificaciones más estrictas.
Mejores prácticas para type hints
- Sé consistente: Anota todas las funciones y métodos públicos.
- Usa
Anycon moderación: Desactiva la verificación de tipos para ese valor. - Prefiere tipos concretos sobre
Anyuobject. - Usa
Optionalpara valores que pueden ser None. - Aprovecha
Protocolpara subtipado estructural (duck typing con seguridad de tipos). - Mantén los type hints actualizados al refactorizar.
- Ejecuta un verificador de tipos en CI para detectar problemas temprano.
Errores comunes y cómo evitarlos
- Ignorar errores de tipo: No silencies mypy; entiende y corrige el problema.
- Abusar de
Any: Anula el propósito de los type hints. - Olvidar anotar los tipos de retorno: Especialmente para funciones que devuelven None.
- Usar argumentos por defecto mutables con type hints: Esto es un problema aparte de Python, pero los type hints no lo detectarán.
- No actualizar los hints tras cambios: Lleva a una falsa confianza.
Type hints en la práctica: un pequeño ejemplo
Considera una función que procesa una lista de números y devuelve el promedio. Sin type hints, no está claro qué tipos se esperan.
def average(numbers):
return sum(numbers) / len(numbers)
Con type hints:
from typing import List
def average(numbers: List[float]) -> float:
return sum(numbers) / len(numbers)
Ahora, si alguien pasa una lista de cadenas, mypy lo señalará.
Integrando type hints en tu flujo de trabajo
Para aprovechar al máximo los type hints, intégralos en tu proceso de desarrollo:
- Añade type hints gradualmente a bases de código existentes.
- Configura tu IDE para mostrar errores de tipo.
- Agrega un paso de verificación de tipos a tu pipeline de CI.
- Usa hooks de pre-commit para ejecutar mypy antes de los commits.
Por ejemplo, un paso simple en un flujo de trabajo de GitHub Actions:
- name: Type check
run: mypy .
Preguntas frecuentes
¿Los type hints afectan el rendimiento en tiempo de ejecución?
No, los type hints se ignoran en tiempo de ejecución. Se almacenan en __annotations__ pero no impactan la velocidad de ejecución.
¿Puedo usar type hints en versiones antiguas de Python?
Los type hints se introdujeron en Python 3.5. Para versiones anteriores, puedes usar anotaciones basadas en comentarios (por ejemplo, # type: int), pero se recomienda actualizar a una versión de Python compatible.
¿Cuál es la diferencia entre List y list en los type hints?
List de typing se usa en Python 3.5-3.8. En Python 3.9+, puedes usar el list integrado directamente. Ambos son equivalentes para la verificación de tipos.
¿Listo para mejorar la calidad de tu código? Empieza añadiendo type hints a una función hoy y ejecuta mypy para ver los beneficios. Para más herramientas de desarrollo, echa un vistazo a nuestro JSON Formatter para embellecer y validar tus datos JSON sin esfuerzo.