.. | ||
decoradores_clas.py | ||
decoradores_func.py | ||
README.md |
Decoradores
Decoradores de Funciones
Son los mas comunes, es una función que toma otra función como argumento, y extiende
la funcionalidad de esta sin modificarla. Permite nueva funcionalidad a una funcion existente.
ej.
import functools
def mi_decorador(func):
@functools.wraps(func)
def funcion_envoltura(*args, **kwargs):
# hacer algo...
result func(*args, **kwargs)
# hacer algo...
return result
return funcion_envoltura
@mi_decorador
def una_funcion():
pass
Las funciones en Python son objetos de primera clase, es decir, como cualquier otro objeto,
estas pueden ser definidas dentro de una función, pasarse como argumento a una función, o
ser devueltas por una función.
Usos típicos:
Implementacion de timers de ejecución.
Decoradores debug para obtener información adicional de la función que llama al decorador y sus arguentos.
Como comprobación de agumentos que son requeridos para el correcto uso de alguna función.
Registrar funciones como plug-ins con decoradores.
Ejemplo basico
import functools
def inicio_final_decorador(func):
def envoltorio():
print("\nInicio")
func()
print("Final")
return envoltorio
@inicio_final_decorador
def imprime_nombre():
print("Pepe")
#imprime_nombre = inicio_final_decorador(imprime_nombre)
imprime_nombre()
# Inicio
# Pepe
# Final
Decorador con argumento (*args, *kwargs)
import functools
def mi_deco(func):
@functools.wraps(func)
def agregado(*args):
"""
Fución que envuelve a la función pasada como argumento
"""
print("\nSumando 5")
func(*args)
print("Fin")
return agregado
@mi_deco
def add5(x):
"""
Fución que suma 5 a número pasado como argumento
"""
print(x + 5)
add5(4)
# Identidad de la función
print(help(add5))
print(add5.__name__)
"""
Esto se corrige con el módulo functools
Help on function agregado in module __main__:
agregado(*args)
Fución que envuelve a la función pasada como argumento
"""
"""
usando @functools.wraps(func)
Help on function add5 in module __main__:
add5(x)
Fución que suma 5 a número pasado como argumento
(END)
"""
Decorador con argumento
def repetir(veces):
def decorador_repetir(func):
@functools.wraps(func)
def envoltorio(*args, **kwargs):
for _ in range(veces):
result = func(*args, **kwargs)
return result
return envoltorio
return decorador_repetir
@repetir(veces=3)
def saludo(nombre):
print(f'Hola {nombre}')
saludo('Roobeeerrrt')
Decoradores anidados
def decor_ini_fin(func):
@functools.wraps(func)
def envolt(*args, **kwargs):
print('\nInicio')
result = func(*args, **kwargs)
print('Fin')
return result
return envolt
def debug(func):
@functools.wraps(func)
def envoltorio(*args, **kwargs):
args_repr = [repr(a) for a in args]
kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()]
firma = ", ".join(args_repr + kwargs_repr)
print(f"Llamado a {func.__name__}({firma})")
result = func(*args, **kwargs)
print(f"{func.__name__!r} returned {result!r}")
return result
return envoltorio
@debug
@decor_ini_fin
def di_hola(nombre):
saludo = f'Hola {nombre}'
print(saludo)
return saludo
di_hola('Fernando')
Decoradores de Clases
Ejemplo contador de llamadas
class ContadLLamada:
def __init__(self, func):
self.func = func
self.num_llamadas = 0
def __call__(self, *args, **kwargs):
self.num_llamadas += 1
print(f'Se ha ejecutado {self.num_llamadas} veces')
return self.func(*args, **kwargs)
@ContadLLamada
def saluda():
print('Hola')
@ContadLLamada
def despide():
print('Chao')
saluda()
# Se ha ejecutado 1 veces
# Hola
saluda()
# Se ha ejecutado 2 veces
# Hola
saluda()
# Se ha ejecutado 3 veces
# Hola
despide()
# Se ha ejecutado 1 veces
# Chao
saluda()
# Se ha ejecutado 4 veces
# Hola
despide()
# Se ha ejecutado 2 veces
# Chao
despide()
# Se ha ejecutado 3 veces
# Chao