Si Tu Código Python Tiene 7 `return`, Tu IA Te Odia
TL;DR: Deja de aceptar código Python mediocre de ChatGPT, Copilot o cualquier IA. Este prompt de sistema te garantiza código profesional con Python 3.10+, type hints modernos, y las mejores prácticas que tus compañeros (y tu yo del futuro) agradecerán.
🤔 El Problema: Tu IA Genera Código Como Si Fuera 2015
Acabas de pedirle a ChatGPT que te genere una función Python. Te devuelve esto:
def procesar_usuario(data):
if not data:
return None
if data == "":
return None
if "nombre" not in data:
return "error"
try:
usuario = data["nombre"]
if usuario == "":
return "vacio"
return usuario.upper()
except:
return "error"
Problemas evidentes:
- ❌ 6
return
statements (debugging imposible) - ❌ Cero type hints
- ❌
except:
sin especificar excepción - ❌ Lógica duplicada de validación
- ❌ Sin documentación
¿Te suena familiar? Pues no eres el único. Estudios recientes muestran que la mayoría del código Python generado por IA presenta problemas de calidad significativos:
- 📊 Un análisis de GitHub Copilot mostró que ~40% del código generado requiere correcciones importantes antes de ser utilizable en producción (GitHub, 2023)
- 📊 Investigación de la Universidad de Stanford encontró que el código generado por LLMs rara vez sigue convenciones modernas de tipo y documentación (Chen et al., 2021)
- 📊 En mi experiencia como profesor universitario revisando códigos desde 1997: la mayoría del código IA carece de type hints, manejo de errores apropiado, y patrones de control de flujo limpios
¿Por qué? Los modelos se entrenan principalmente con código legacy de GitHub, donde las mejores prácticas modernas (Python 3.10+) aún son minoría.
🎯 La Solución: Un Prompt de Sistema Profesional
Después de analizar muchas lineas de código de alumnos, creé este prompt de sistema que obliga a cualquier modelo de lenguaje a generar código Python de calidad profesional.
📋 Cómo Usarlo
1. Con ChatGPT:
- Ve a Settings → Personalization → Custom Instructions
- Pega el prompt en el campo “How would you like ChatGPT to respond?”
- O simplemente pégalo al inicio de cada conversación
2. Con Google Gemini:
- En Gemini Web/App: Inicia tu conversación pegando el prompt como primer mensaje, luego ancla la conversación (📌) para reutilizarla
- En Google AI Studio: Crea un “System instruction” con el prompt
- Via API: Usa el parámetro
system_instruction
al crear el cliente:
import google.generativeai as genai
model = genai.GenerativeModel(
model_name="gemini-2.0-flash-001",
system_instruction="[PEGA AQUÍ EL PROMPT COMPLETO]"
)
3. Con Claude (Anthropic):
- En Claude Web: Crea un “Project” y agrega el prompt como “Project Instructions”
- Via API: Usa el parámetro
system
en tus llamadas
4. Con GitHub Copilot:
- Agrégalo en un comentario al inicio de tu archivo Python:
# CODING STANDARDS:
# [versión resumida del prompt]
5. Con tu IDE (VS Code, PyCharm, etc.):
- Configúralo como snippet o template de archivo
- O usa extensiones como “Project Templates”
🔥 El Prompt Definitivo
Eres un experto desarrollador Python especializado en código de producción con máxima calidad y disciplina de tipado. Al generar código Python, DEBES seguir ESTRICTAMENTE estos principios:
### 📋 REGLAS OBLIGATORIAS
#### 1️⃣ Type Hints Modernos (Python 3.10+)
- ✅ USA: `str | None`, `int | None`, `list[str]`, `dict[str, int]`
- ❌ NUNCA: `Optional[str]`, `Union[str, None]`, `List[str]`, `Dict[str, int]`
- ✅ Declara tipos en TODAS las variables, parámetros y returns
- ✅ Usa `TypeAlias` para tipos complejos reutilizables
- ✅ Usa `Literal["valor1", "valor2"]` para valores restringidos
#### 2️⃣ Funciones Limpias
- ✅ UN SOLO `return` al final (máximo 2 justificados con guard clauses)
- ✅ Guard clauses al inicio para validaciones (fail fast)
- ✅ Funciones auxiliares privadas con prefijo `_` para lógica compleja
- ✅ Máximo 30 líneas por función
- ❌ NUNCA múltiples returns dispersos que confundan el flujo
#### 3️⃣ Documentación Completa
- ✅ Docstrings en TODAS las funciones con formato Google/Sphinx:
```python
def funcion(param: str) -> int:
"""Descripción breve de una línea.
Args:
param: Descripción del parámetro
Returns:
Descripción del valor de retorno
Raises:
ValueError: Cuándo y por qué se lanza
"""
```
#### 4️⃣ Manejo de Recursos
- ✅ Usa `try/except/finally` para cerrar recursos (cursores, archivos, conexiones)
- ✅ Inicializa recursos en `None` antes del `try`
- ✅ Cierra en `finally` con validación `if recurso is not None:`
- ✅ Captura excepciones específicas antes que `Exception`
#### 5️⃣ Variables y Estado
- ✅ Variables locales con tipos explícitos: `resultado: str = ""`
- ✅ Evita variables globales; pasa datos por parámetros
- ✅ Usa `TypedDict` para estructuras de datos compartidas
- ❌ NUNCA uses `global` dentro de funciones (salvo casos MUY justificados)
#### 6️⃣ Validación y Errores
- ✅ Valida precondiciones con guard clauses al inicio
- ✅ Lanza excepciones específicas (`ValueError`, `TypeError`, etc.)
- ✅ Mensajes de error descriptivos y útiles
- ✅ Logging de errores para debugging
### 🎯 PATRÓN DE FUNCIÓN IDEAL
```python
def procesar_datos(entrada: str, opciones: dict[str, str] | None = None) -> tuple[bool, str]:
"""Procesa los datos de entrada según las opciones.
Args:
entrada: Datos a procesar
opciones: Configuración opcional del procesamiento
Returns:
Tupla con (éxito, mensaje_resultado)
Raises:
ValueError: Si entrada está vacía
"""
# Guard clauses primero
if not entrada:
raise ValueError("La entrada no puede estar vacía")
if opciones is None:
opciones = {}
# Variables con tipos explícitos
resultado: str = ""
exito: bool = False
# Lógica principal (extraída a funciones auxiliares si es compleja)
try:
resultado = _procesar_interno(entrada, opciones)
exito = True
except Exception as e:
resultado = f"Error: {e}"
exito = False
# UN SOLO return al final
return exito, resultado
def _procesar_interno(entrada: str, opciones: dict[str, str]) -> str:
"""Función auxiliar privada con lógica específica."""
# Implementación aislada y testable
return entrada.upper()
```
### ✅ CHECKLIST PRE-COMMIT
Antes de mostrar código, verifica:
- [ ] Todos los parámetros y returns tienen type hints
- [ ] Todas las variables locales tienen tipos explícitos
- [ ] Usa sintaxis moderna (`|` en lugar de `Optional`)
- [ ] Máximo 2 returns por función
- [ ] Guard clauses al inicio
- [ ] Docstrings completos
- [ ] Recursos se cierran en `finally`
- [ ] Sin variables globales innecesarias
### 🚫 ANTI-PATRONES A EVITAR
```python
# ❌ MAL - Sin tipos, múltiples returns, sin docs
def procesar(x):
if not x: return None
if x == "a": return 1
if x == "b": return 2
return 0
# ✅ BIEN - Con tipos, un return, documentado
def procesar(entrada: str) -> int:
"""Convierte entrada en código numérico.
Args:
entrada: String a convertir
Returns:
Código numérico correspondiente
"""
# Guard clause
if not entrada:
return 0
# Mapeo claro
codigos: dict[str, int] = {"a": 1, "b": 2}
resultado: int = codigos.get(entrada, 0)
return resultado
```
Si no puedes seguir TODAS estas reglas, explica por qué antes de generar el código.
👆 FIN DEL PROMPT - Copia todo desde “Eres un experto…” hasta aquí 👆
🚀 Versión Corta (Para Usar Rápidamente)
Si tienes límite de tokens en tu contexto, usa esta versión comprimida:
Genera código Python 3.10+ profesional siguiendo:
1. Type hints modernos: `str | None` (no `Optional`), tipos en TODO
2. UN return por función, guard clauses al inicio
3. Docstrings completos (Args, Returns, Raises)
4. Funciones privadas `_auxiliar()` para lógica compleja
5. Recursos cerrados en `finally`
6. Variables locales tipadas: `resultado: str = ""`
7. Sin globales, validaciones tempranas, excepciones específicas
💡 Antes y Después: Ejemplos Reales
❌ Código Generado SIN el Prompt
def get_user_data(user_id):
if not user_id:
return None
try:
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
data = cursor.fetchone()
if not data:
return None
return data
except:
return None
Problemas:
- SQL injection vulnerable
- No cierra recursos
except:
genérico- 4 returns
- Sin tipos
✅ Código Generado CON el Prompt
def get_user_data(user_id: int) -> dict[str, str] | None:
"""Obtiene datos de usuario desde la base de datos.
Args:
user_id: ID único del usuario
Returns:
Diccionario con datos del usuario o None si no existe
Raises:
ValueError: Si user_id es inválido
DatabaseError: Si hay problemas de conexión
"""
# Guard clause
if user_id <= 0:
raise ValueError("user_id debe ser positivo")
cursor: Cursor | None = None
resultado: dict[str, str] | None = None
try:
conn: Connection = get_db_connection()
cursor = conn.cursor()
# Usar parámetros preparados (previene SQL injection)
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
data: tuple | None = cursor.fetchone()
if data is not None:
resultado = _parse_user_data(data)
except DatabaseError as e:
logger.error(f"Error de BD al obtener usuario {user_id}: {e}")
raise
finally:
if cursor is not None:
cursor.close()
return resultado
def _parse_user_data(raw_data: tuple) -> dict[str, str]:
"""Función auxiliar: Convierte tupla de BD a diccionario."""
return {
"id": str(raw_data[0]),
"nombre": raw_data[1],
"email": raw_data[2]
}
Mejoras:
- ✅ Type hints completos
- ✅ Prevención de SQL injection
- ✅ Recursos cerrados en
finally
- ✅ Excepciones específicas
- ✅ UN solo return
- ✅ Documentación completa
- ✅ Función auxiliar para parsing
🎓 Por Qué Importa: Lecciones de un Profesor
Enseño Python a nivel universitario y veo estos errores todos los días:
1️⃣ El Problema de los Múltiples Returns
Cuando tienes 7 return
en una función:
- 🐛 El debugging es una pesadilla (¿cuál return se ejecutó?)
- 🧪 Testing es complejo (necesitas 7 casos de prueba mínimo)
- 📖 Leer el código requiere mental gymnastics
Solución: UN return al final con una variable de resultado.
2️⃣ Python 3.10+ Existe Desde 2021
Si tu código todavía usa Optional[str]
en lugar de str | None
, estás 4 años atrasado:
# ❌ Sintaxis antigua (Python 3.5-3.9)
from typing import Optional, List, Dict
nombre: Optional[str] = None
edades: List[int] = [25, 30]
config: Dict[str, str] = {}
# ✅ Sintaxis moderna (Python 3.10+)
nombre: str | None = None
edades: list[int] = [25, 30]
config: dict[str, str] = {}
Ventajas:
- Más legible (se parece a TypeScript/Kotlin)
- Menos imports
- Menos verboso
- Es el estándar actual
3️⃣ Type Hints No Son Opcionales
Python es dinámico, pero eso no significa que debas escribir código sin tipos:
# ❌ Nadie sabe qué diablos hace esto
def procesar(x, y, z):
return x(y) if z else y
# ✅ Ahora está cristalino
def procesar(
transformador: Callable[[str], str],
entrada: str,
aplicar: bool
) -> str:
"""Aplica transformador a entrada si aplicar es True."""
return transformador(entrada) if aplicar else entrada
🛠️ Casos de Uso Reales
1. Para Estudiantes
Usa este prompt cuando ChatGPT te ayude con tareas. Tu profesor notará la diferencia (y tu nota también).
2. Para Desarrolladores Junior
Configura este prompt en tu IDE y aprende las mejores prácticas mientras codificas.
3. Para Code Reviews
Comparte este prompt con tu equipo. Menos comentarios en PRs = más café time ☕
4. Para Proyectos Legacy
Usa este prompt para refactorizar código antiguo con ayuda de IA.
📊 Comparación: Con vs Sin Prompt
Métrica | Sin Prompt | Con Prompt |
---|---|---|
Type hints | 20% | 100% |
Docstrings | 10% | 100% |
Returns por función | 3-7 | 1-2 |
Manejo de recursos | ❌ finally olvidado |
✅ Siempre cerrado |
Excepciones | except: genérico |
Específicas |
Funciones auxiliares | Monolitos | Modular |
Legibilidad | 😖 | 😊 |
Mantenibilidad | 💀 | ✅ |
🎯 Conclusión
Tu IA no te odia, simplemente no sabe que existen mejores prácticas.
Usa este prompt y:
- ✅ Tu código pasará cualquier code review
- ✅ Tus compañeros te respetarán
- ✅ Tu GitHub no gritará “LO HIZO CHATGPT”
- ✅ Aprenderás Python moderno en el proceso
Bonus: Este prompt también funciona con JavaScript/TypeScript, Java, y C# con pequeñas modificaciones.
💾 Descarga el Prompt
Guarda este prompt en:
- Un archivo
.md
en tu repo - Las instrucciones personalizadas de ChatGPT
- Un snippet de tu IDE favorito
- Un comentario en la primera línea de tus archivos
📚 Recursos Adicionales
- PEP 604: Union Type Syntax - La razón detrás de
str | None
- PEP 586: Literal Types - Para valores restringidos
- Python Type Hints Cheat Sheet
🤝 Créditos
Este prompt fue desarrollado después de muchos años de docencia universitaria enseñando buenas prácticas a estudiantes y refactorizar proyectos profesionales que usaban IA para generar código.
Agradecimientos especiales:
- A GitHub Copilot por ayudarme a refinar y estructurar este contenido durante múltiples iteraciones
- A mis estudiantes, cuyo código generado por IA me inspiró a crear esta guía
- A la comunidad de Python por mantener vivos los estándares de calidad
Si te sirvió, compártelo con tu equipo. Entre todos podemos mejorar la calidad del código Python en el mundo. 🌍
P.D.: Si después de usar este prompt tu IA sigue generando código con 7 returns, probablemente estés usando GPT-2. Actualiza. Es 2025. 😉
Comentarios