Patrones de Python: Mejores Prácticas
Reglas para una estructura de Python legible y mantenible, desde EAFP hasta la conexión de dependencias.
Cómo Usar Esta Lista
- Aplica durante las revisiones de diseño antes de añadir nuevas capas de abstracción.
- Prefiere un patrón claro por límite; no mezcles estilos de dispatch en el mismo módulo.
- Aplica con ruff, mypy/pyright y pruebas de arquitectura siempre que sea posible.
A - Modismos y Legibilidad
- Prefiere EAFP cuando el éxito es común. Las rutas lineales felices superan a las guardas anidadas; captura excepciones específicas.
- Usa
withpara pares de adquisición/liberación. Archivos, locks y transacciones necesitan un desmontaje garantizado. - Recurre a dispatch de diccionarios antes de que las cadenas
elifsuperen las cinco ramas. Registra plugins explícitamente. - Nombra las funciones de fábrica
cosa_desde_env/construir_cosa. Los llamadores reconocen los ayudantes de la raíz de composición. - La legibilidad cuenta más que la astucia. Si un junior no puede rastrearlo en cinco minutos, simplifica.
B - Estructura y Acoplamiento
- Inyecta dependencias a través de constructores. No hay singletons ocultos de
get_db()en métodos de servicio. - Depende de protocolos, conecta concretos en la raíz. El código de la aplicación se mantiene testeable e intercambiable.
- Usa objetos nulos para colaboradores opcionales que no hacen nada (no-op). No para dependencias de producción requeridas.
- Publica eventos de dominio a través de una interfaz de bus. Los manejadores permanecen pequeños; los fallos se registran por manejador.
- Divide los objetos "dios" por responsabilidad antes de añadir el décimo método. Extrae protocolos primero.
C - Valores Predeterminados y Seguridad
- Nunca uses argumentos predeterminados mutables. Centinela
Nonemás un contenedor nuevo dentro de la función. - Usa centinelas explícitos cuando
Nonees un dato válido. Documenta las comprobacionesispara objetosUNSET. - Valida los constructores en
build(), no en los setters. Mantén el estado parcial del constructor interno. - Evita E/S y red en tiempo de importación. Los hooks de inicio y los manejadores de ciclo de vida son dueños de los efectos secundarios.
- Captura excepciones específicas; nunca
exceptgenérico. Registra el contexto; vuelve a lanzar a menos que la supresión sea contractual.
D - Disciplina de Abstracción
- Regla de tres antes de extraer interfaces. Espera tres duplicaciones reales, no futuros imaginados.
- Prefiere funciones y dataclasses sobre herencia profunda. La composición y el dispatch cubren la mayoría de los casos de Python.
- Reemplaza la proliferación de flags booleanos con enums o estrategias. Los modos son tipos, no cuatro parámetros
True/False. - Mantén las APIs públicas explícitas -
**kwargsmínimos. TypedDict o Pydantic en los límites HTTP/CLI. - Documenta las claves de registro y los nombres de eventos válidos.
StrEnumoLiteralpara verificación estática.
E - Revisión y Evolución
- Escanea en busca de anti-patrones en módulos de alta rotación trimestralmente. Argumentos predeterminados mutables y errores ignorados primero.
- Una prueba de integración por dispatcher/registro. Las claves y tipos desconocidos fallan con mensajes claros.
- Refactoriza la extracción por protocolo en PRs pequeños. La fachada delega hasta que los llamadores migran.
- Empareja el patrón con el tamaño del problema. Los scripts permanecen simples; los servicios obtienen inyección y eventos.
- Enlaza ADRs al elegir bus vs llamadas directas. Los futuros lectores conocerán el compromiso aceptado.
Preguntas Frecuentes
¿Cuál es la práctica de mayor impacto para código nuevo?
Inyección de constructor más protocolos: las pruebas mejoran inmediatamente sin frameworks.
¿Cuándo debo saltarme los patrones por completo?
Scripts de un solo uso de ~100 líneas: funciones simples, sin bus, sin constructor.
¿Cómo aplico el dispatch de diccionarios?
Módulo de registro central, claves tipadas como StrEnum y pruebas que fallan con claves desconocidas.
¿Son necesarios los gestores de contexto basados en clases?
No. @contextmanager cubre la mayoría de los casos; clases cuando el estado de enter/exit es sustancial.
¿Cómo se relaciona esto con PEP 20?
Explícito, legible, plano: estas prácticas operacionalizan el Zen de Python en la arquitectura.
¿Debería cada servicio emitir eventos?
Solo para límites a los que otros módulos se suscriben. Los pasos internos permanecen como llamadas directas.
¿Cómo migro cadenas `elif` de forma segura?
Introduce un diccionario que mapee las ramas existentes; mantén elif delegando hasta que la cobertura coincida; elimina las ramas.
¿Cambia FastAPI los consejos de DI?
Depends() es inyección de parámetros en las rutas: mismo principio, ámbito gestionado por el framework por solicitud.
¿Qué reglas de lint ayudan más?
ruff B006 (argumentos predeterminados mutables), E722 (except genérico) y pyright en implementaciones de protocolos.
¿Cómo enseño patrones a los juniors?
Empieza con Conceptos Básicos de Patrones de Python, luego revisa un anti-patrón por sprint.
Relacionado
- Conceptos Básicos de Patrones de Python - ejemplos prácticos
- Anti-Patrones Comunes - errores a evitar
- EAFP vs LBYL - estilo de excepciones
- Inyección de Dependencias en Python - detalles de conexión
Versiones del 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+.