Decoradores Personalizados en Clases-1
Decoradores Personalizados en Clases - Ejemplo Sencillo
Concepto básico:
Un decorador personalizado es una función que modifica el comportamiento de otra función o clase.
Ejemplo 1: Decorador simple para funciones
def mi_decorador(funcion):
def wrapper():
print("Algo pasa ANTES de la función")
funcion()
print("Algo pasa DESPUÉS de la función")
return wrapper
@mi_decorador
def saludar():
print("¡Hola!")
saludar()
# Output:
# Algo pasa ANTES de la función
# ¡Hola!
# Algo pasa DESPUÉS de la funciónEjemplo 2: Decorador para métodos de clase
def logear_metodo(funcion):
def wrapper(self, *args, **kwargs):
print(f"📝 Ejecutando: {funcion.__name__}")
resultado = funcion(self, *args, **kwargs)
print(f"✅ Completado: {funcion.__name__}")
return resultado
return wrapper
class Calculadora:
@logear_metodo
def sumar(self, a, b):
return a + b
@logear_metodo
def restar(self, a, b):
return a - b
calc = Calculadora()
calc.sumar(5, 3)
# Output:
# 📝 Ejecutando: sumar
# ✅ Completado: sumar
calc.restar(10, 4)
# Output:
# 📝 Ejecutando: restar
# ✅ Completado: restarEjemplo 3: Decorador con parámetros
def repetir(veces):
def decorador(funcion):
def wrapper(*args, **kwargs):
for i in range(veces):
print(f"Ejecución {i+1}:")
funcion(*args, **kwargs)
return wrapper
return decorador
class Mensajero:
@repetir(veces=3)
def enviar_mensaje(self, mensaje):
print(f"Enviando: {mensaje}")
msg = Mensajero()
msg.enviar_mensaje("¡Hola Mundo!")
# Output:
# Ejecución 1:
# Enviando: ¡Hola Mundo!
# Ejecución 2:
# Enviando: ¡Hola Mundo!
# Ejecución 3:
# Enviando: ¡Hola Mundo!Ejemplo 4: Decorador para validar datos
def validar_edad(funcion):
def wrapper(self, edad):
if edad < 0:
print("❌ Edad no puede ser negativa")
return
if edad > 120:
print("❌ Edad no puede ser mayor a 120")
return
return funcion(self, edad)
return wrapper
class Persona:
def __init__(self, nombre):
self.nombre = nombre
@validar_edad
def establecer_edad(self, edad):
self.edad = edad
print(f"✅ {self.nombre} tiene {self.edad} años")
persona = Persona("Ana")
persona.establecer_edad(25) # ✅ Ana tiene 25 años
persona.establecer_edad(-5) # ❌ Edad no puede ser negativa
persona.establecer_edad(150) # ❌ Edad no puede ser mayor a 120Ejemplo 5: Decorador que mide tiempo
import time
def medir_tiempo(funcion):
def wrapper(*args, **kwargs):
inicio = time.time()
resultado = funcion(*args, **kwargs)
fin = time.time()
print(f"⏰ {funcion.__name__} tardó {fin-inicio:.2f} segundos")
return resultado
return wrapper
class Procesador:
@medir_tiempo
def procesar_lento(self):
time.sleep(1) # Simula proceso lento
return "Procesado"
proc = Procesador()
proc.procesar_lento()
# Output: ⏰ procesar_lento tardó 1.00 segundosEn resumen:
Un decorador personalizado es como agregar superpoderes a tus funciones/métodos:
@superpoder # ← Así se usa
def mi_funcion(): # ← Tu función normal
pass¿Ves lo simple que es? ¡Son como "envoltorios mágicos" para tus funciones
Decoradores Personalizados: Los Asistentes Mágicos del Restaurante 🎩🍽️
Imagina que tienes un restaurante de lujo donde cada chef (método) puede tener asistentes especializados (decoradores) que le ayudan sin cambiar su forma de cocinar.
El Restaurante Mágico
# NUESTROS ASISTENTES MÁGICOS (decoradores)
def asistente_verificador(func):
"""El asistente que verifica los ingredientes"""
def asistente(*args, **kwargs):
print("🔍 ASISTENTE: Verificando que los ingredientes estén frescos...")
resultado = func(*args, **kwargs)
print("✅ ASISTENTE: Ingredientes aprobados!")
return resultado
return asistente
def asistente_tiempo(func):
"""El asistente que controla el tiempo de cocción"""
def asistente(*args, **kwargs):
print("⏱️ ASISTENTE: Iniciando timer...")
resultado = func(*args, **kwargs)
print("⏱️ ASISTENTE: Tiempo perfecto!")
return resultado
return asistente
def asistente_presentacion(func):
"""El asistente que decora el plato"""
def asistente(*args, **kwargs):
resultado = func(*args, **kwargs)
plato_decorado = f"🎨 {resultado} con decoración especial"
return plato_decorado
return asistenteLos Chefs y Sus Asistentes
class Restaurante:
def __init__(self, nombre_chef):
self.nombre_chef = nombre_chef
@asistente_verificador
@asistente_tiempo
def preparar_ensalada(self):
print(f"👨🍳 {self.nombre_chef}: Preparando ensalada...")
return "Ensalada César"
@asistente_presentacion
@asistente_verificador
def preparar_postre(self):
print(f"👨🍳 {self.nombre_chef}: Preparando postre...")
return "Tiramisú"
# Vamos al restaurante
restaurante = Restaurante("Chef Antonio")
print("=== PREPARAR ENSALADA ===")
plato1 = restaurante.preparar_ensalada()
print(f"Plato listo: {plato1}")
print("\n=== PREPARAR POSTRE ===")
plato2 = restaurante.preparar_postre()
print(f"Plato listo: {plato2}")Salida:
=== PREPARAR ENSALADA ===
🔍 ASISTENTE: Verificando que los ingredientes estén frescos...
⏱️ ASISTENTE: Iniciando timer...
👨🍳 Chef Antonio: Preparando ensalada...
⏱️ ASISTENTE: Tiempo perfecto!
✅ ASISTENTE: Ingredientes aprobados!
Plato listo: Ensalada César
=== PREPARAR POSTRE ===
🔍 ASISTENTE: Verificando que los ingredientes estén frescos...
👨🍳 Chef Antonio: Preparando postre...
Plato listo: 🎨 Tiramisú con decoración especialAsistentes con Superpoderes Especiales
def asistente_repetir(veces):
"""El asistente que repite la receta varias veces"""
def asistente_real(func):
def ayudante(*args, **kwargs):
resultados = []
for i in range(veces):
print(f"🔄 ASISTENTE: Preparando lote {i+1} de {veces}")
resultado = func(*args, **kwargs)
resultados.append(resultado)
return resultados
return ayudante
return asistente_real
def asistente_calidad(nivel):
"""El asistente que controla la calidad según el nivel"""
def asistente_real(func):
def ayudante(*args, **kwargs):
if nivel == "alto":
print("⭐ ASISTENTE: Modo CALIDAD PREMIUM activado")
elif nivel == "medio":
print("👍 ASISTENTE: Modo CALIDAD ESTÁNDAR activado")
resultado = func(*args, **kwargs)
if nivel == "alto":
resultado += " ⭐ (CALIDAD PREMIUM)"
return resultado
return ayudante
return asistente_real
class Panaderia:
def __init__(self, nombre_panadero):
self.nombre_panadero = nombre_panadero
@asistente_repetir(3)
def hacer_pan(self):
print(f"🥖 {self.nombre_panadero}: Amasando pan...")
return "Pan recién horneado"
@asistente_calidad("alto")
def hacer_pastel(self):
print(f"🎂 {self.nombre_panadero}: Decorando pastel...")
return "Pastel de chocolate"
# Vamos a la panadería
panaderia = Panaderia("Panadero Carlos")
print("=== HACER PAN (3 LOTES) ===")
panes = panaderia.hacer_pan()
print(f"Resultado: {panes}")
print("\n=== HACER PASTEL (CALIDAD ALTA) ===")
pastel = panaderia.hacer_pastel()
print(f"Resultado: {pastel}")El Gran Restaurante con Todos los Asistentes
class GranRestaurante:
def __init__(self, nombre):
self.nombre = nombre
self.platos_preparados = 0
# Asistente personalizado para contar platos
def contar_platos(func):
def asistente(self, *args, **kwargs):
self.platos_preparados += 1
resultado = func(self, *args, **kwargs)
print(f"📊 ASISTENTE: Plato número {self.platos_preparados} preparado!")
return resultado
return asistente
@asistente_verificador
@asistente_tiempo
@contar_platos
def plato_especial(self, nombre_plato):
print(f"👨🍳 {self.nombre}: Creando {nombre_plato}...")
return f"🎉 {nombre_plato} ESPECIAL"
@asistente_presentacion
@contar_platos
def plato_rapido(self, nombre_plato):
print(f"👨🍳 {self.nombre}: Preparando rápido {nombre_plato}...")
return nombre_plato
# El restaurante en acción
restaurante_lujo = GranRestaurante("Chef Master")
print("=== PLATO ESPECIAL ===")
plato1 = restaurante_lujo.plato_especial("Salmón a la parrilla")
print(f"Resultado: {plato1}")
print("\n=== PLATO RÁPIDO ===")
plato2 = restaurante_lujo.plato_rapido("Sopa del día")
print(f"Resultado: {plato2}")
print(f"\n📈 Total platos preparados: {restaurante_lujo.platos_preparados}")Analogía Completa:
RESTAURANTE DE LUJO (Tu Clase)
CHEF PRINCIPAL (Métodos normales)
├── preparar_plato() - Sabe cocinar
└── Su trabajo principal es crear platos
ASISTENTES MÁGICOS (Decoradores)
├── 🕵️♂️ ASISTENTE VERIFICADOR → Revisa ingredientes
├── ⏱️ ASISTENTE TIEMPO → Controla cocción
├── 🎨 ASISTENTE PRESENTACIÓN → Decora el plato
├── 🔄 ASISTENTE REPETIR → Prepara múltiples porciones
└── ⭐ ASISTENTE CALIDAD → Controla nivel de calidad
CADA PLATO puede tener DIFERENTES ASISTENTES¿Por qué esto es mágico? ✨
El chef no se distrae: Solo se concentra en cocinar
Los asistentes son reutilizables: Un mismo asistente ayuda a muchos chefs
Puedes mezclar y combinar: Diferentes combinaciones para diferentes platos
Fácil de mantener: Si cambia un asistente, afecta a todos automáticamente
Ejemplo del Mundo Real:
# Asistentes para un sistema bancario
def verificar_sesion(func):
def asistente(self, *args, **kwargs):
if not self.sesion_activa:
return "❌ Por favor inicia sesión primero"
return func(self, *args, **kwargs)
return asistente
def registrar_transaccion(func):
def asistente(self, *args, **kwargs):
resultado = func(self, *args, **kwargs)
print(f"📝 Transacción registrada: {func.__name__}")
return resultado
return asistente
class Banco:
def __init__(self):
self.sesion_activa = False
def login(self):
self.sesion_activa = True
return "✅ Sesión iniciada"
@verificar_sesion
@registrar_transaccion
def retirar_dinero(self, cantidad):
return f"💰 Retiraste ${cantidad}"¡Los decoradores son como tener un equipo de asistentes mágicos que hacen que tu código sea más poderoso sin esfuerzo
Comentarios
Publicar un comentario