Domina el tipado en Python con ejemplos prácticos: aprende a anotar parámetros, definir el retorno con la flecha -> y tipar listas, diccionarios, tuplas y listas anidadas. Verás cómo el editor usa los tipos para autocompletar y alertar errores, cuándo usar any sin abusar y cómo MyPy ayuda a mantener el código limpio a medida que el proyecto crece.
¿Cómo tipar funciones en Python con parámetros y retorno?
Anotar funciones hace explícito qué datos reciben y devuelven. Se usan dos puntos para parámetros y el operador flecha para el retorno. Así, el editor identifica tipos y ofrece autocompletado.
# función tipada: parámetros y retornodefsuma_clara(a:int, b:int)->int:return a + b
Parámetros tipados con ":" y su tipo: int, str, etc.
Retorno con "->" y el tipo esperado.
El editor muestra tipos y autocompleta según las anotaciones.
¿Qué ventaja práctica ofrece el tipado en proyectos grandes?
Entiendes qué enviar a cada función sin abrir su archivo.
Reduces errores al integrar módulos en muchos archivos.
Documentas el código de forma viva y verificable.
¿Cómo tipar listas, diccionarios y estructuras anidadas?
Para colecciones, usa genéricos con corchetes. Con list indicas que es una lista; con tipos internos, restringes su contenido. Esto habilita autocompletado correcto y validaciones de incompatibilidad.
# lista de artículos: cada elemento es un diccionario con datos como titlearticles:list[dict]=[{"title":"Primer post"},{"title":"Segundo post"},]# lista de listas restringida a stringsmatriz:list[list[str]]=[["artículos","otro"],["más","items"],]
Usa list[...] para tipar listas con su contenido.
El editor solo sugiere métodos válidos de lista tras el punto.
Anida tipos: list[list[str]] para listas de listas de strings.
Tipos básicos disponibles: int, str, list, dict y tuple.
¿Qué ocurre si agregas un tipo incompatible?
El editor marca el item como incompatible con el tipo declarado.
Evitas errores al momento de construir o ejecutar.
Corriges de inmediato antes de que el fallo se propague.
¿Cuándo usar any y cómo apoyarte en mypy?
Cuando migras código sin tipado, any permite avanzar mientras decides los tipos reales. Úsalo con moderación para no perder los beneficios del tipado.
# uso controlado de anyfrom typing importanyarticulos3:list[any]=["texto",123,{"title":"válido"},]
any acepta cualquier tipo de dato.
Útil al mover un proyecto sin typing a código tipado.
No sobreabusar: mejor sin tipado que llenarlo de any en todos los archivos.
Instala la extensión MyPy para detectar errores y empezar a limpiar el código mientras construyes el proyecto.
¿Tienes dudas sobre cómo tipar una estructura específica o una función compleja? Cuéntalo en los comentarios y comparte tu ejemplo para recibir sugerencias.
El editor solo sugiere métodos válidos según el tipo.
⚠️ 4️⃣ Qué pasa con tipos incompatibles
🚫 Si insertas un valor que no coincide con el tipo declarado:
⚡ El editor marca el error.
🛠️ Puedes corregir antes de ejecutar.
🧯 Evitas errores en cascada durante el desarrollo.
✅ Tipado = detección temprana de errores.
🔐 5️⃣ Uso de Any + MyPy
🧩 Cuándo usar Any
Durante migraciones de código sin tipado.
Cuando no conoces aún el tipo exacto.
⚠️ No abuses de él: reduce la utilidad del tipado.
Ejemplo:
from typing import Any
articulos3: list[Any] = [
"texto",
123,
{"title": "válido"},
]
Sobre el reto, por ejemplo, asi quedaria la función fetch_news:
deffetch_news(api_name:str,*args: Any,**kwargs: Any)->dict[str, Any]|str:"""Funcion flexible para conectar con la API de noticias""" base_config:dict[str,int]={"timeout":30,"retries":3,} config:dict[str, Any]={**base_config,**kwargs,} api_clients:dict[str, Any]={"newsapi": newsapi_client,"guardian": guardian_client,} client: Any = api_clients[api_name]return client(*args,**config)
Muy buena solución!
No te adelantes con el typing! Veremos Any en el futuro!
Esto es especial en muchos aspectos, yo me los he llegado a encontrar con mucha frecuencia en FastApi que usa los tipados para validar con pydantic de fondo 👀, a priori parece que no pero es demasiado útil.
Pydantic usa MUY bien los tipos, que bueno que los hayas aprendido!
variable =42# type: intprint(f"Variable: {variable} del tipo {type(variable).__name__}")variable ="Hola"# type: strprint(f"Variable: {variable} del tipo {type(variable).__name__}")variable =3.14# type: floatprint(f"Variable: {variable} del tipo {type(variable).__name__}")variable =True# type: boolprint(f"Variable: {variable} del tipo {type(variable).__name__}")variable =[1,2,3]# type: listprint(f"Variable: {variable} del tipo {type(variable).__name__}")variable =(1,2,3)# type: tupleprint(f"Variable: {variable} del tipo {type(variable).__name__}")variable ={"name":"Carlos","age":30}# type: dictprint(f"Variable: {variable} del tipo {type(variable).__name__}")variable ={"Carlos","Madrigal"}# type: setprint(f"Variable: {variable} del tipo {type(variable).__name__}")# Type hints: Son anotaciones que indican el tipo de dato que se espera en una variable, función o clase.# No afectan el funcionamiento del programa, pero ayudan a mejorar la legibilidad y el mantenimiento del código.# Ejemplos de type hints# Variable: tipo = valorotra_variable:int=10print(f"Otra variable: {otra_variable} del tipo {type(otra_variable).__name__}")# Otra variable: 10 del tipo int, se conoce tu tipo a nivel del código#Python no obliga a usar ese tipo definido, se puede cambiar el tipo de la variable en otra asignacionotra_variable ="Hola"# type: strprint(f"Otra variable: {otra_variable} del tipo {type(otra_variable).__name__}")# Tipar datos pero permitir vacios, con operado pipelineuser_id:int|None=Noneprint(f"User ID: {user_id} del tipo {type(user_id).__name__}")user_id =123print(f"User ID: {user_id} del tipo {type(user_id).__name__}")# Variablesname:str="Carlos"age:int=30is_student:bool=Trueheight:float=1.75# Funciones# def nombre_funcion(parametro: tipo) -> tipo_retorno:# return valordefsuma_clara(a:int, b:int)->int:return a + b
print("================================================================================")print("Type hints en funciones")print("================================================================================")resultado = suma_clara(1,2)print(f"Resultado: {resultado} del tipo {type(resultado).__name__}")defgreet(name:str)->str:returnf"Hola, {name}"print("================================================================================")print("Type hints en listas")print("================================================================================")#Listasarticles:list[str]=["Python","Java","C++"]print(f"Articles: {articles} del tipo {type(articles).__name__}")#A pesar de que se tipa la lista como list[str], se puede agregar otro tipo de datoarticles.append("Rust")print(f"Articles: {articles} del tipo {type(articles).__name__}")articulos:list[dict]=[{"name":"Carlos","age":30},{"name":"Madrigal","age":25}]print(f"Articulos: {articulos} del tipo {type(articulos).__name__}")articulos_dos:list[list[str]]=[["Python","Java","C++"],["Rust","Go","C#"]]print(f"Articulos dos: {articulos_dos} del tipo {type(articulos_dos).__name__}")from typing import Any
articulos_tres:list[list[Any]]=[["Python","Java","C++",123,True,3.14],["Rust","Go","C#",123,True,3.14]]print(f"Articulos tres: {articulos_tres} del tipo {type(articulos_tres).__name__}")#Diccionariosuser:dict[str,int]={"name":"Carlos","age":30}print(f"User: {user} del tipo {type(user).__name__}")#A pesar de que se tipa el diccionario como dict[str, int], se puede agregar otro tipo de datouser["email"]="[EMAIL_ADDRESS]"print(f"User: {user} del tipo {type(user).__name__}")#Tuplascoordinates:tuple[int,int]=(1,2)print(f"Coordinates: {coordinates} del tipo {type(coordinates).__name__}")#A pesar de que se tipa la tupla como tuple[int, int], se puede agregar otro tipo de datocoordinates =(1,2,3)print(f"Coordinates: {coordinates} del tipo {type(coordinates).__name__}")# ClasesclassPerson:def__init__(self, name:str, age:int): self.name = name
self.age = age
# Ejemplos de usoprint(greet(name))# Type hints en funcionesdefadd(a:int, b:int)->int:return a + b
print(add(1,2))# Type hints en clasesclassPerson:def__init__(self, name:str, age:int): self.name = name
self.age = age
# Ejemplos de usoperson = Person("Carlos",30)print(person.name)print(person.age)