Decoradores para Principiantes
Analogía: El Asistente Personal
Imagina que tienes un chef (tu función) que cocina platos. Un decorador sería como un asistente personal que:
Prepara la cocina antes de que el chef empiece
Limpia todo después de que el chef termina
No modifica cómo el chef cocina
El asistente envuelve/al chef y añade funcionalidad extra sin cambiar su trabajo principal.
Ejemplo 1: Decorador "Saludador" 🎉
# El decorador (asistente personal)
def decorador_saludar(funcion_original):
def funcion_envoltura():
print("🎉 ¡La función va a empezar!") # Esto pasa ANTES
funcion_original() # Aquí se ejecuta la función original
print("🎊 ¡La función terminó!") # Esto pasa DESPUÉS
return funcion_envoltura
# La función original (el chef)
def mi_funcion():
print("👨🍳 Estoy cocinando/computando...")
# Aplicar el decorador manualmente
mi_funcion_decorada = decorador_saludar(mi_funcion)
print("=== SIN DECORADOR ===")
mi_funcion()
print("\n=== CON DECORADOR ===")
mi_funcion_decorada()Output:
=== SIN DECORADOR ===
👨🍳 Estoy cocinando/computando...
=== CON DECORADOR ===
🎉 ¡La función va a empezar!
👨🍳 Estoy cocinando/computando...
🎊 ¡La función terminó!Ahora con la sintaxis @ (más limpia):
def decorador_saludar(funcion_original):
def funcion_envoltura():
print("🎉 ¡La función va a empezar!")
funcion_original()
print("🎊 ¡La función terminó!")
return funcion_envoltura
# Usando @ es equivalente a: mi_funcion = decorador_saludar(mi_funcion)
@decorador_saludar
def mi_funcion():
print("👨🍳 Estoy cocinando/computando...")
# Simplemente llamamos la función
mi_funcion()Ejemplo 2: Decorador "Contador de Llamadas" 🔢
def contador_llamadas(funcion_original):
# Variable que recuerda cuántas veces se llamó
contador = 0
def funcion_envoltura():
# Usamos nonlocal para modificar la variable del scope exterior
nonlocal contador
contador += 1
print(f"📞 Esta es la llamada número: {contador}")
return funcion_original()
return funcion_envoltura
@contador_llamadas
def saludar():
print("¡Hola mundo!")
# Probemos llamar la función varias veces
saludar()
saludar()
saludar()Output:
📞 Esta es la llamada número: 1
¡Hola mundo!
📞 Esta es la llamada número: 2
¡Hola mundo!
📞 Esta es la llamada número: 3
¡Hola mundo!Ejemplo 3: Decorador "Verificador de Edad" 🎂
def verificar_edad(funcion_original):
def funcion_envoltura(edad):
if edad < 18:
print("❌ Acceso denegado. Eres menor de edad.")
return
else:
print("✅ Acceso permitido. Eres mayor de edad.")
return funcion_original(edad)
return funcion_envoltura
@verificar_edad
def entrar_al_bar(edad):
print("🍻 ¡Bienvenido al bar!")
# Probemos con diferentes edades
print("=== EDAD 16 ===")
entrar_al_bar(16)
print("\n=== EDAD 25 ===")
entrar_al_bar(25)Output:
=== EDAD 16 ===
❌ Acceso denegado. Eres menor de edad.
=== EDAD 25 ===
✅ Acceso permitido. Eres mayor de edad.
🍻 ¡Bienvenido al bar!¿Qué está pasando realmente?
Sin decorador:
def mi_funcion():
print("Hola")
# Llamada normal
mi_funcion() # Output: "Hola"Con decorador:
def decorador(func):
def wrapper():
print("Antes")
func()
print("Después")
return wrapper
@decorador
def mi_funcion():
print("Hola")
# Esto es equivalente a:
# mi_funcion = decorador(mi_funcion)
mi_funcion()
# Output:
# "Antes"
# "Hola"
# "Después"Resumen Visual
FUNCIÓN ORIGINAL: [ print("Hola") ]
CON DECORADOR:
[ DECORADOR ] → [ print("Antes") ] → [ print("Hola") ] → [ print("Después") ]
↑
Envuelve la función originalPuntos Clave para Principiantes:
Un decorador es una función que toma otra función y devuelve una nueva función
Extiende comportamiento sin modificar la función original
La sintaxis @ es solo azúcar sintáctica para hacerlo más legible
Piensa en ello como: "antes y después" de la función original
Comentarios
Publicar un comentario