development:python:decorators

Python decoradores

def decorator(func):
  print("Decorator")
  return func
 
@decorator
def Hello():
  print("Hello World")
 
Hello() 
# [Output]:
# Decorator
# Hello World
#print_args: Función decoradora
def printArgs(func):
  def innerFunc(*args, **kwargs):
    print(args)
    print(kwargs)
    return func(*args, **kwargs)
 
  return innerFunc
 
#foobar: Función decorada
@printArgs
def foobar(x, y, z):
  return x * y + z
 
print(foobar(3, 5, z=10))
# (3, 5)
# {'z': 10}
# 25 = 3 * 5 + 10

(se puede crear una funcion estática @staticmethod en una clase e invocarla de esa manera)

class Decorator(object):
  """Clase de decorador simple."""
  def __init__(self, func):
    self.func = func
 
  def __call__(self, *args, **kwargs):
    print('Antes de ser llamada la función.')
    retorno = self.func(*args, **kwargs)
    print('Despues de ser llamada la función.')
    print(retorno)
    return retorno
 
@Decorator
def function():
  print('Dentro de la función.')
  return "Retorno"
 
function()
# Antes de ser llamada la función.
# Dentro de la función.
# Despues de ser llamada la función.
# 'Retorno'
import types
print(isinstance(function, types.FunctionType))
# False
print(type(function))
# <class '__main__.Decorator'>
from types import MethodType
 
class Decorator(object):
 
  def __init__(self, func):
    self.func = func
 
  def __call__(self, *args, **kwargs):
    print('Dentro del Decorador.')
    return self.func(*args, **kwargs)
 
  def __get__(self, instance, cls):
    # Retorna un método si se llama en una instancia
    return self if instance is None else MethodType(self, instance)
 
class Test(object):
  @Decorator
  def __init__(self):
    print("Dentro de la función decorada")
 
a = Test()
# Dentro del Decorador.
# Dentro de la función decorada
class MyDec(object):
  def __init__(self, flag):
    self.flag = flag
 
  def __call__(self, original_func):
    decorator_self = self
    def wrappee(*args, **kwargs):
      print('en decorador antes de wrapee ', decorator_self.flag)
      original_func(*args,**kwargs)
      print('en decorador despues de wrapee', decorator_self.flag)
    return wrappee
 
@MyDec(flag='foo de fa fa')
def bar(a,b,c):
  print('En bar(...) : ',a,b,c)
 
if __name__ == "__main__":
  bar(1, "Hola", True)
 
#Out:
# en decorador antes de wrapee  foo de fa fa
# en bar 1 Hola True
# en decorador despues de wrapee foo de fa fa
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
 
from types import MethodType
 
class Decorator():
    def __init__(self,func):
        print(f"Decorator.__init__")
        self.func = func
 
    def __call__(self, *args, **kwargs):
        print("Decorator pre")
        print(nom_funcio := self.func.__name__)
        print(B.classvar)
 
        retorn = self.func(*args,nom_funcio=nom_funcio,**kwargs)
        print("Decorator post")
 
        return retorn
 
    def __get__(self,instance,cls):
        # Retorna un método si se llama en una instancia
        return self if instance is None else MethodType(self, instance)
 
 
class Decorator2():
    def __init__(self,func):
        print(f"Decorator2.__init__")
        self.func = func
 
    def __call__(self):
        print("Decorator2 pre")
        print(self.func.__name__)
        print(B.classvar)
 
        self.func(self)
        print("Decorator2 post")
 
 
class A():
    @staticmethod
    def decorator(func):
        def wrapper(*args,**kwargs):
            print("A.decorator pre")
 
            print(nom_funcio := func.__name__)
            print(B.classvar)
 
            retorn = func(*args,nom_funcio=nom_funcio,**kwargs)
            print("A.decorator post")
 
            return retorn
 
 
        return wrapper
 
 
class B(A):
    classvar = None
 
    def __init__(self,var=None):
        self.var = var
        B.classvar = var
 
    def decorator(func):
        def wrapper(*args,**kwargs):
            print("decorator pre")
 
            print(nom_funcio := func.__name__)
            print(B.classvar)
 
            retorn = func(*args,nom_funcio=nom_funcio,**kwargs)
 
            print("decorator post")
 
            return retorn
 
 
        return wrapper  
 
    @Decorator
    def run(self,nom_funcio=None):
        print(f"B.run({nom_funcio})")
 
    @Decorator2
    def run2(self,nom_funcio=None):
        print(f"B.run2({nom_funcio})")
 
    @A.decorator
    def run3(self,nom_funcio=None):
        print(f"B.run3({nom_funcio})")
 
    @decorator
    def run4(self,nom_funcio=None):
        print(f"B.run4({nom_funcio})")
 
 
o = B('mate')
o.run()
o.run2()
o.run3()
o.run4()
print(o.__dict__)
  • classvar se usa como variable de intercambio de información, pero es una variable de clase. Varias instancias para diferentes cometidos darian conflictos.
  • development/python/decorators.txt
  • Darrera modificació: 15/09/2024 23:48
  • per mate