Tipado Estático y Anotaciones de Tipo (Type Hints)
Python es un lenguaje de tipado dinámico, lo que significa que el intérprete comprueba los tipos en tiempo de ejecución. Sin embargo, a partir de Python 3.5+ (PEP 484) y su consolidación en versiones modernas (3.9 - 3.12), Python soporta Type Hints (pistas o anotaciones de tipo).
Las anotaciones de tipo no alteran la ejecución en runtime, pero transforman el desarrollo profesional al permitir:
- Detección temprana de errores mediante analizadores estáticos como
mypyopyright. - Autocompletado y refactorización inteligente en IDEs (VSCode, PyCharm).
- Auto-documentación viva de contratos y firmas de funciones.
1. Anotaciones básicas en variables y funciones #
1# Variables con tipo explícito 2nombre: str = "Elena" 3edad: int = 28 4salario: float = 3450.50 5activo: bool = True 6 7# Funciones con tipos en parámetros y valor de retorno (->) 8def calcular_iva(precio: float, porcentaje: float = 0.21) -> float: 9 return precio * (1 + porcentaje) 10 11total: float = calcular_iva(100.0) 12print(f"Total con IVA: {total} €")Salida de consola Total con IVA: 121.0 €
2. Colecciones y Tipos Compuestos Modernos (PEP 585) #
Desde Python 3.9+, ya no es necesario importar List, Dict, Set o Tuple del módulo typing; puedes usar los tipos estándar nativos directamente con corchetes:
1# Lista de enteros 2puntuaciones: list[int] = [98, 85, 92] 3 4# Diccionario con clave string y valor entero 5inventario: dict[str, int] = {"manzanas": 10, "naranjas": 25} 6 7# Tupla de longitud fija y tipos específicos 8coordenadas: tuple[float, float, str] = (40.4168, -3.7038, "Madrid") 9 10# Conjunto de cadenas únicas 11etiquetas: set[str] = {"python", "backend", "fastapi"}
3. Tipos Unión y Valores Nulos (PEP 604) #
Operador tubería | (Python 3.10+) #
Sustituye a Union y Optional del módulo antiguo typing:
1# Acepta un entero o un flotante 2def formatear_numero(valor: int | float) -> str: 3 return f"{valor:.2f}" 4 5# Acepta un string o None (antiguo Optional[str]) 6def buscar_usuario(id_usuario: int) -> str | None: 7 if id_usuario == 1: 8 return "Admin" 9 return None
4. El módulo typing para casos avanzados #
Cuando necesitas expresar restricciones más ricas, el módulo typing ofrece herramientas fundamentales:
1from typing import Any, Callable, Literal 2 3# Literal: restringe el valor a un conjunto exacto de opciones 4ModoApertura = Literal["r", "w", "a"] 5 6def abrir_archivo(ruta: str, modo: ModoApertura) -> None: 7 print(f"Abriendo {ruta} en modo '{modo}'") 8 9# Callable: define funciones como argumentos (tipo: [[args], retorno]) 10def procesar_lista(valores: list[int], transformador: Callable[[int], int]) -> list[int]: 11 return [transformador(x) for x in valores] 12 13cuadrado = lambda n: n * n 14print(procesar_lista([1, 2, 3], cuadrado))Salida de consola [1, 4, 9]
5. Alias de Tipo y Sintaxis type (Python 3.12+) #
Puedes definir alias legibles para tipos complejos. En Python 3.12 se introdujo la palabra clave formal type:
1# Python 3.12+ 2type Matriz2D = list[list[float]] 3type RespuestaAPI = dict[str, str | int | bool] 4 5def procesar_respuesta(respuesta: RespuestaAPI) -> None: 6 print(f"Estado recibido: {respuesta.get('estado')}")
6. Verificación Estática con mypy #
Las anotaciones son ignoradas en ejecución por Python. Para validarlas automáticamente en tu pipeline de CI/CD:
1pip install mypy 2mypy mi_archivo.py
Si pasas un argumento incompatible, mypy avisará antes de que el código llegue a producción:
1error: Argument 1 to "calcular_iva" has incompatible type "str"; expected "float"
Resumen del tema
Conceptos clave #
- Type Hints: anotaciones que declaran el tipo esperado de variables, parámetros y retornos (
def f(x: int) -> str:). - Colecciones Genéricas (Python 3.9+): uso directo de
list[T],dict[K, V],set[T],tuple[T, ...]. - Operador Unión
|(Python 3.10+): simplificaint | floatystr | None(sustituto deUnionyOptional). - Módulo
typing: utilidades avanzadas comoLiteral,Callable,Any,TypeVaryGeneric. - Herramientas Estáticas:
mypyypyrightejecutan análisis estático para garantizar la consistencia de tipos antes del despliegue.
Qué debes recordar #
Usa anotaciones de tipo nativas (int | None, list[str]) en todas tus funciones públicas para maximizar la robustez, el autocompletado del IDE y la prevención de errores con mypy.