Decoradores
Un decorador es una función que modifica el comportamiento de otra función o clase. Es una manera de envolver una función con otra para añadirle funcionalidad adicional, sin modificar su código original.
1. Cómo funcionan? #
En Python, las funciones son objetos de primera clase, lo que significa que pueden ser pasadas como argumentos a otras funciones. Un decorador es, de hecho, una función que toma otra función como argumento, la modifica y devuelve una nueva función que la reemplaza.
2. Ejemplo básico de decorador: #
1def mi_decorador(func): 2 def wrapper(): 3 print("Antes de llamar a la función.") 4 func() 5 print("Después de llamar a la función.") 6 return wrapper 7 8def saludo(): 9 print("¡Hola!") 10 11# Usando el decorador manualmente 12saludo = mi_decorador(saludo) 13 14saludo()Salida de consola Antes de llamar a la función. ¡Hola! Después de llamar a la función.
3. Usando la sintaxis de decoradores #
Python tiene una sintaxis especial para aplicar decoradores de manera más elegante. Se usa el símbolo @ seguido del nombre del decorador justo encima de la definición de la función a decorar:
1def mi_decorador(func): 2 def wrapper(): 3 print("Antes de llamar a la función.") 4 func() 5 print("Después de llamar a la función.") 6 return wrapper 7 8@mi_decorador 9def saludo(): 10 print("¡Hola!") 11 12saludo()Salida de consola Antes de llamar a la función. ¡Hola! Después de llamar a la función.
Esto es equivalente a hacer:
1saludo = mi_decorador(saludo)
4. Decoradores con parámetros #
Si la función decorada toma parámetros, el decorador debe ser modificado para pasárselos adecuadamente:
1def mi_decorador(func): 2 def wrapper(*args, **kwargs): 3 print("Antes de llamar a la función.") 4 result = func(*args, **kwargs) 5 print("Después de llamar a la función.") 6 return result 7 return wrapper 8 9@mi_decorador 10def saludo(nombre): 11 print(f"¡Hola, {nombre}!") 12 13saludo("Juan")Salida de consola Antes de llamar a la función. ¡Hola, Juan! Después de llamar a la función.
Resumen del tema
Conceptos clave #
- Patrón Decorador: función que recibe como parámetro otra función y devuelve una nueva función envolvente (wrapper) extendiendo su comportamiento sin alterar su código fuente.
- Azúcar Sintáctico
@decorador: equivalente a reasignarfuncion = decorador(funcion). - Soporte Universal de Parámetros (
*args, **kwargs): la función interna wrapper debe aceptar*args, **kwargsy retornar el resultado defunc(*args, **kwargs). - Conservación de Metadatos (
functools.wraps): buena práctica de decorar la función wrapper con@functools.wraps(func)para preservar el nombre (__name__) y docstrings originales.
Qué debes recordar #
Los decoradores (@decorador) envuelven funciones para extender dinámicamente su comportamiento (logging, autenticación, timing) de forma limpia y reutilizable.