Un decorador es un tipo especial de función que toma una función y devuelve una función o toma una clase y devuelve una clase. Bueno, puede ser cualquier invocable (es decir, funciones, clases, métodos, ya que pueden llamarse) y puede devolver cualquier cosa, también puede tomar un método. Esto también se llama metaprogramación , ya que una parte del programa intenta modificar otra parte del programa en tiempo de compilación.
Sumerjámonos en los decoradores de python y descubramos qué pueden hacer. Esto no cubrirá los conceptos básicos o los decoradores con parámetros, sino algunos ejemplos útiles para ilustrar el caso.
Consulte el siguiente artículo para obtener los conceptos básicos de los decoradores de Python
Básicamente, un decorador toma un invocable, cualquier objeto que implemente el método especial __call()__
se denomina invocable, agrega alguna funcionalidad y devuelve un invocable.
Ejemplo 1:
# Python program to demonstrate # decorators # Creating a decorator def decorated_func(func): def inner(): print("This is decorated function") func() return inner() def ordinary_func (): print("This is ordinary function") decorated = decorated_func(ordinary_func) decorated
Producción:
This is decorated function This is ordinary function
En el ejemplo que se muestra arriba, decorated_func()
es un decorador. En resumen, un decorador actúa como un envoltorio que envuelve un objeto (no altera el objeto original) y agrega una nueva funcionalidad al objeto original. Esta es una construcción común, por lo que Python tiene una característica de sintaxis (llamada Decorator
) para simplificar esto. Por ejemplo,
Este:
@decorated_func def ordinary_func(): print("This is ordinary function")
es equivalente a:
def ordinary_func(): print("This is ordinary function") decorated = decorated_func(ordinary_func)
Un ejemplo sencillo sería:
Ejemplo 2:
Entrada:
def mul_decorator(func): def wrapper(*args, **kwargs): print('function', func.__name__, 'called with args - ', / args, 'and kwargs - ', kwargs) result = func(*args, **kwargs) print('function', func.__name__, 'returns', result) return result return wrapper @mul_decorator def mul(a, b): return a * b mul(3, 3) mul(3, b = 6)
Producción:
function mul called with args - (3, 3) and kwargs - {} function mul returns 9 function mul called with args - (3,) and kwargs - {'b': 6} function mul returns 18
También puedes usar los empotrados como decoradores
Ejemplo 3:
# func will be func = type(func) -> <class 'function'> @type def func(): return 42 print(func) # print doesn't return anything, so func == None @print def func2(): return 42 # Prints None print(func2)
Producción:
<class 'function'> <function func2 at 0x7f135f067f28> None
Puedes reemplazar el objeto decorado con otra cosa
Ejemplo 4:
# Creating a decorator class function_1: def __init__(self, func): self.func = func self.stats = [] def __call__(self, *args, **kwargs): try: result = self.func(*args, **kwargs) except Exception as e: self.stats.append((args, kwargs, e)) raise e else: self.stats.append((args, kwargs, result)) return result @classmethod def function_2(cls, func): return cls(func) @function_1.function_2 def func(x, y): return x / y print(func(6, 2)) print(func(x = 6, y = 4)) func(5, 0) print(func.stats) print(func)
Producción:
3.0 1.5
Traceback (most recent call last): File "/home/1ba974e44c61e303979b3ee120b6b066.py", line 29, in func(5, 0) File "/home/1ba974e44c61e303979b3ee120b6b066.py", line 11, in __call__ raise e File "/home/1ba974e44c61e303979b3ee120b6b066.py", line 8, in __call__ result = self.func(*args, **kwargs) File "/home/1ba974e44c61e303979b3ee120b6b066.py", line 23, in func return x / y ZeroDivisionError: division by zero
Observe cómo el original "func"
fue reemplazado por una instancia de "function_1"
, que se puede usar de la misma manera que la función original.
Puede crear una relación con otros objetos en el sistema
Ejemplo 5:
def dict_from_func(func): return {func.__name__: func} activity = {} @activity.update @dict_from_func def mul(a, b): return a * b @activity.update @dict_from_func def add(a, b): return a + b print(mul) print(activity) print(activity['mul'](2, 5))
Producción:
None {'mul': <function mul at 0x7f0d2209fe18>, 'add': <function add at 0x7f0d220a2158>} 10
Aquí, en el ejemplo 5, hemos utilizado dict.update
el método como decorador, aunque no esté destinado a ello. Esto es posible porque dict_from_func
devuelve un dict y dict.update
toma un dict como argumento.
En realidad, esto:
@activity.update @dict_from_func def mul(a, b): return a * b
es igual a esto –
def mul(a, b): return a * b mul = activity.update(dict_from_func(mul))
Conclusión
Los decoradores son una característica interesante y sorprendente y se pueden usar para una variedad de propósitos. No es solo «función o clase que toma una función o una clase y devuelve una función o una clase» .
Publicación traducida automáticamente
Artículo escrito por SadanandNerurkar y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA