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 wrapperEn este ejemplo
mi_decoradores una función que recibe una funciónfunc- Dentro define una función
wrapper(podría tener cualquier nombre) - La función
wrapperutiliza la funciónfuncrecibida - Finalmente
mi_decoradordevuelve 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ónEn este ejemplo:
- Cuando se invoca a
saludar, en realidadmi_decorador“toma el control” mi_decoradorrecibe la funciónsaludar, y devuelve la funciónwrapperque 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,
repetires un decorador que acepta un argumenton- Este repite la ejecución de la función decorada
nveces
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ésEn este ejemplo, funcion está decorada primero por decorador2 y luego por decorador1, mostrando cómo se puede encadenar múltiples decoradores.