Mejores Prácticas para Iteradores y Decoradores
Directrices para la iteración perezosa, la higiene de decoradores y las tuberías componibles: los patrones que mantienen los servicios de Python seguros en memoria y depurables.
Cómo Usar Esta Lista
- Revísala al construir tuberías ETL o procesadores de logs.
- Aplícala en frameworks con muchos decoradores (autenticación, reintentos, métricas).
- Combínala con profiling cuando las cadenas de iteradores se vuelvan profundas.
- Úsala en la revisión de código para
lambdaen bucles y@wrapsfaltantes.
A - Iteración
- Usa generadores o expresiones generadoras para flujos más grandes que la memoria. Materializa solo en el consumidor final cuando sea necesario.
- Compón tuberías como pequeñas funciones generadoras. Cada etapa realiza una transformación, lo que facilita las pruebas.
- Prefiere
itertoolsparachain,islice,groupby,product. Probados en batalla y perezosos. - Ordena antes de
groupbycuando agrupes por clave. El requisito de clave consecutiva es fácil de olvidar. - Documenta iteradores de pasada única. Los llamadores no deben asumir la repetición sin
teeolist().
B - Generadores y Recursos
- Usa
try/finallyo@contextmanagerdentro de generadores que manejan archivos/sockets. Los consumidores pueden detenerse prematuramente. - Cierra generadores con
.close()en pruebas cuando la limpieza sea importante. ActivaGeneratorExiten elyield. - Evita efectos secundarios en la definición del generador; los efectos se ejecutan al consumir. La semántica perezosa sorprende a los recién llegados.
- Usa
yield fromen lugar de buclesfor/yieldmanuales. Delegación y propagación de retorno más claras. - Limita los iteradores infinitos con
isliceo condiciones debreak.count()ycycle()nunca se detienen solos.
C - Decoradores
- Aplica siempre
@functools.wrapsen funciones envoltorio. Conserva__name__, la documentación y las anotaciones. - Mantén las pilas de decoradores poco profundas y ordenadas de forma consistente. Documenta el orden de
classmethod/staticmethod. - Parametriza a través de fábricas de decoradores (
def retry(n):). Evita la configuración mutable global en decoradores. - No suprimas excepciones a menos que el propósito del decorador sea la supresión. Vuelve a lanzar o encadena con
from. - Prefiere el middleware/Depends de FastAPI para el ámbito de la solicitud. Decoradores de función para utilidades puras.
D - functools y Caché
- Caché solo funciones puras con argumentos hasheables (
lru_cache). Llama acache_clearcuando las entradas cambien externamente. - Establece
maxsizeenlru_cachepara espacios de claves ilimitados. Previene fugas de memoria. - Usa
singledispatchpara extensión abierta por tipo. No largas cadenas deisinstanceen un solo módulo. - Usa
partialpara vincular configuración, no para ocultar parámetros requeridos. Mantén las firmas públicas legibles.
E - Gestores de Contexto
- Usa
withpara archivos, bloqueos, transacciones de bases de datos y configuración temporal. No abras sin una ruta de cierre. - Usa
ExitStackcuando el número de contextos se determine en tiempo de ejecución. Listas de archivos dinámicas, pilas de plugins. - Devuelve
Falsede__exit__a menos que estés suprimiendo deliberadamente. Los fallos ocultos corrompen el estado. - Prefiere
@contextmanagerpara configuración/desmontaje simples de menos de 15 líneas. Basado en clases para objetos reutilizables. - Prueba las rutas de reversión inyectando excepciones dentro del bloque
with.
Preguntas Frecuentes
¿generador o list comprehension?
Generador cuando el flujo es grande o de pasada única. Lista cuando necesites len, reutilización o indexación.
¿cuántas etapas en una tubería?
Divide cuando cada etapa tenga una responsabilidad digna de un nombre; evita anidamientos anónimos de 10 líneas.
¿decorador en la API pública de una biblioteca?
Documenta el orden de apilamiento y la preservación de metadatos; los consumidores confían en __name__ en los logs.
¿lru_cache en métodos?
Caché por función; los argumentos del método incluyen self. Considera una función fuera de la clase o __hash__ en self inmutable.
¿iterador tee?
Solo cuando debas bifurcar una pasada única; la memoria crece con la divergencia.
¿prácticas de generadores async?
Ver sección de asyncio; usa async with para adquisición, async for para consumo.
¿cómo probar tuberías perezosas?
list(pipeline(data)) en pruebas; verifica la limpieza intermedia con mocks en close.
¿reduce sigue estando bien?
Bien para plegados raros; un bucle explícito suele ser más claro para equipos nuevos en el estilo funcional.
¿decorador de clase vs herencia?
Decorador para registro/metadatos; herencia para implementación de comportamiento compartido.
¿error más grande con iteradores?
Materializar listas intermedias gigantes entre etapas de map/filter; mantente perezoso hasta el límite.
Relacionados
- Generadores y yield - tuberías perezosas
- Escribiendo Decoradores - wraps y fábricas
- Gestores de Contexto - protocolo de limpieza
- Comprensiones y Expresiones Generadoras - conceptos básicos de
genexp
Versiones de Stack: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, y uv 0.6+.