Buenas Prácticas Fundamentales de Python
Hábitos centrales que mantienen el código Python legible, correcto y mantenible antes de recurrir a frameworks o herramientas de datos. Trata esto como una lista de verificación de incorporación para cada nuevo módulo o repositorio.
Cómo Usar Esta Lista
- Revísala al iniciar un nuevo paquete o al incorporar a un compañero de equipo.
- Aplícala durante la revisión de código para archivos que toquen fundamentos (E/S, importaciones, funciones).
- Vuelve a visitarla después de incidentes relacionados con la mutabilidad, la codificación o la deriva del entorno.
- Combínala con CI de ruff/mypy para que las reglas se vuelvan automáticas, no aspiracionales.
A - Entorno y Herramientas
- Crea un entorno virtual antes de instalar paquetes de terceros. Nunca contamines el Python del sistema (PEP 668).
- Fija las dependencias con
pyproject.tomly un archivo de bloqueo (uv.lock). CI y clones reproducibles. - Dirígete a características de Python 3.14+ solo cuando la versión del runtime lo permita. Documenta
requires-pythonenpyproject.toml. - Ejecuta
ruff checkyruff formaten cada PR. Retroalimentación rápida de estilo y linting. - Habilita mypy o pyright incrementalmente en módulos nuevos. Los tipos se amortizan en los límites de la API.
B - Estilo de Código y Legibilidad
- Sigue la nomenclatura PEP 8: funciones
snake_case, clasesPascalCase, constantesUPPER. - Prefiere f-strings sobre el formateo
%yformat()para código nuevo. Más claro y rápido. - Usa
pathlib.Pathen lugar de la manipulación de cadenas deos.path. Uniones seguras multiplataforma. - Mantén las funciones cortas con una responsabilidad clara. Extrae cuando el anidamiento exceda dos niveles.
- Escribe docstrings en módulos, clases y funciones públicas. Resumen de una línea más parámetros cuando no son obvios.
C - Datos y Corrección
- Nunca uses argumentos predeterminados mutables (
def f(x=[])). UsaNoney asigna en el interior. - Usa
Decimalpara dinero, no float binario. Evita sorpresas de0.1 + 0.2en facturación. - Especifica
encoding="utf-8"en toda la E/S de archivos de texto. Previene errores predeterminados de la plataforma. - Copia estructuras anidadas con
copy.deepcopycuando la independencia importa. Las copias superficiales comparten listas internas. - Usa
isinstancepara comprobaciones de tipo, notype(x) is Clsen subclases. Amigable con el polimorfismo.
D - Flujo de Control y APIs
- Prefiere comprensiones o generadores sobre bucles
appendmanuales al transformar secuencias. Legible y a menudo más rápido. - Usa
match/casepara ramificación estructural en diccionarios y dataclasses. Más limpio que cadenasifprofundas. - Expón opciones solo por palabra clave después de
*en APIs públicas. Previene sitios de llamada ambiguos. - Protege scripts con
if __name__ == "__main__":. Módulos importables sin efectos secundarios. - Ejecuta paquetes con
python -m package.module. Importaciones relativas y__package__correctos.
E - Importaciones y Diseño
- Usa importaciones absolutas en código de aplicación (
from myapp.utils import x). Más claro que las relativas en árboles grandes. - Rompe importaciones circulares con importaciones perezosas o módulos
typescompartidos. Falla rápido en tiempo de diseño cuando sea posible. - Evita sombrear nombres de módulos de la biblioteca estándar (
json.py,types.py). Rompe importaciones misteriosamente. - Adopta el diseño
src/para paquetes instalables. Previene importaciones accidentales desde la raíz del repositorio. - Mantén los efectos secundarios en tiempo de importación al mínimo. Sin red ni base de datos al cargar módulos en bibliotecas.
Preguntas Frecuentes
¿Deben los principiantes memorizar cada regla de PEP 8?
No: configura ruff y concéntrate en la legibilidad. Automatiza los debates de formato.
¿Cuándo está bien el estado global?
Las constantes a nivel de módulo y la configuración en caché de solo lectura están bien. Los globales mutables complican las pruebas; prefiere la inyección.
¿Son obligatorias las anotaciones de tipo en los scripts?
Opcional para scripts desechables. Agrégalas cuando el script crezca o se convierta en un paquete.
¿match o if/elif?
match para estructura (claves de diccionario, eventos tipados). if para condiciones escalares simples.
¿uv o poetry para proyectos nuevos?
Este manual fija uv 0.6+ como la ruta rápida predeterminada. Poetry sigue siendo válido para equipos que ya lo usan como estándar.
¿Qué tan estricto debe ser mypy?
Comienza con módulos nuevos en flags opcionales strict; amplía gradualmente. Modelos Pydantic en los límites HTTP primero.
¿Es la comprensión de listas siempre mejor que un bucle?
Mejor para transformaciones de map/filter. Usa un bucle for cuando los efectos secundarios o la ramificación compleja dominen.
¿Debo usar print para logging?
print está bien para la experiencia de usuario de la CLI. Los servicios deben usar logging con campos estructurados; consulta la sección de errores-logging.
¿Cómo enseño la verdad (truthiness)?
Comparaciones explícitas (is None, len(x) == 0) cuando los valores falsos pero válidos como 0 importan.
¿Cuál es el hábito de mayor impacto?
Entornos aislados con dependencias bloqueadas: todo lo demás falla sin instalaciones reproducibles.
Relacionados
- Fundamentos de Python - recorrido introductorio ejecutable
- Variables, Tipos y Tipado Dinámico - semántica de referencia
- Inicio Rápido de Entornos Virtuales - flujo de trabajo de uv
- Fundamentos de Anotaciones de Tipo - introducción al tipado estático
Versiones de la Pila: 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+.