En Python, un decorador es una función que recibe otra función como argumento y devuelve una nueva función que, generalmente, extiende el comportamiento de la original.
Los decoradores permite modificar o extender el comportamiento de funciones o métodos sin modificar su código fuente.
Se utilizan ampliamente para aspectos transversales como la autenticación, el registro (logging), y la validación, entre otros.
Definir un decorador
Vamos a verlo con un ejemplo
def mi_decorador(func):
def wrapper():
print("Algo se hace antes de la función")
func()
print("Algo se hace después de la función")
return wrapper
En este ejemplo
mi_decorador
es una función que recibe una funciónfunc
- Dentro define una función
wrapper
(podría tener cualquier nombre) - La función
wrapper
utiliza la funciónfunc
recibida - Finalmente
mi_decorador
devuelve la funciónwrapper
Usando un decorador
Ahora, para emplear el decorador se utiliza el símbolo @
seguido del nombre del decorador, antes de la definición de la función que se desea decorar.
@mi_decorador
def saludar():
print("¡Hola desde LuisLlamas.es!")
saludar()
# Salida:
# Algo se hace antes de la función
# ¡Hola desde LuisLlamas.es!
# Algo se hace después de la función
En este ejemplo:
- Cuando se invoca a
saludar
, en realidadmi_decorador
“toma el control” mi_decorador
recibe la funciónsaludar
, y devuelve la funciónwrapper
que la utiliza- Esta agrega comportamiento antes y después de la ejecución de
saludar
Decoradores con argumentos
Los decoradores también pueden aceptar argumentos. Para hacerlo, se necesita anidar funciones:
- Una función externa para aceptar los argumentos del decorador
- Una función interna que acepte la función que será decorada.
Por ejemplo,
def repetir(n):
def decorador(func):
def envoltura(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return envoltura
return decorador
@repetir(3)
def decir_adios():
print("Adiós!")
decir_adios()
# Salida:
# Adiós!
# Adiós!
# Adiós!
En este caso,
repetir
es un decorador que acepta un argumenton
- Este repite la ejecución de la función decorada
n
veces
Decoradores en múltiples niveles
Python permite anidar decoradores, aplicando múltiples decoradores a una misma función.
def decorador1(func):
def envoltura():
print("Decorador 1 antes")
func()
print("Decorador 1 después")
return envoltura
def decorador2(func):
def envoltura():
print("Decorador 2 antes")
func()
print("Decorador 2 después")
return envoltura
@decorador1
@decorador2
def funcion():
print("Función ejecutándose")
funcion()
# Salida:
# Decorador 1 antes
# Decorador 2 antes
# Función ejecutándose
# Decorador 2 después
# Decorador 1 después
En este ejemplo, funcion
está decorada primero por decorador2
y luego por decorador1
, mostrando cómo se puede encadenar múltiples decoradores.