Pregunta

Quiero que construya clases para su uso como decoradores con los siguientes principios intactos:

  1. Debe ser posible apilar múltiples tales decoradores de clase en la parte superior de 1 función.
  2. El puntero del nombre de la función resultante debe ser indistinguible de la misma función sin un decorador, excepto tal vez por sólo el tipo / clase que es.
  3. ordenar del decoradores no deben ser pertinentes a menos que en realidad el mandato de los decoradores. Es decir. decoradores independientes se podrían aplicar en cualquier orden.

Esto es para un proyecto de Django, y el caso específico que estoy trabajando ahora el método necesita 2 decoradores, y que aparezca como una función normal de Python:

@AccessCheck
@AutoTemplate
def view(request, item_id) {}

@AutoTemplate cambia la función para que en lugar de devolver un HttpResponse, simplemente devuelve un diccionario para su uso en el contexto. Se utiliza un RequestContext, y el nombre de la plantilla se infiere a partir del nombre del método y el módulo.

@AccessCheck agrega controles adicionales en el usuario basado en el item_id.

Estoy adivinando que es sólo para obtener el derecho constructor y copiar los atributos adecuados, pero que atribuye es esto?

La siguiente decorador no funcionará como se describo:

class NullDecl (object):
    def __init__ (self, func):
        self.func = func
    def __call__ (self, * args):
        return self.func (*args)

Como se ha demostrado por el siguiente código:

@NullDecl
@NullDecl
def decorated():
    pass

def pure():
    pass

# results in set(['func_closure', 'func_dict', '__get__', 'func_name',
# 'func_defaults', '__name__', 'func_code', 'func_doc', 'func_globals'])
print set(dir(pure)) - set(dir(decorated));

Además, tratar de añadir en el constructor NullDecl, y que funcionará para el primer decorador, pero no el segundo "Func impresión nombre ." -. Como el nombre no podrá contar

Refinado eduffy 's responder un poco, y parece que funciona bastante bien:

class NullDecl (object):
    def __init__ (self, func):
        self.func = func
        for n in set(dir(func)) - set(dir(self)):
            setattr(self, n, getattr(func, n))

    def __call__ (self, * args):
        return self.func (*args)
    def __repr__(self):
        return self.func
¿Fue útil?

Solución

Una clase decoradora que no hace nada se vería así:

class NullDecl (object):
   def __init__ (self, func):
      self.func = func
      for name in set(dir(func)) - set(dir(self)):
        setattr(self, name, getattr(func, name))

   def __call__ (self, *args):
      return self.func (*args)

Y a continuación, se puede aplicar normalmente:

@NullDecl
def myFunc (x,y,z):
   return (x+y)/z

Otros consejos

El decorador módulo le ayuda a escribir decoradores firma-preservación.

Y el PythonDecoratorLibrary podría proporcionar ejemplos útiles para decoradores.

Para crear un decorador que envuelve las funciones en cuestión que los hacen indistinguibles de la función original, use functools.wraps.

Ejemplo:


def mydecorator(func):
    @functools.wraps(func):
    def _mydecorator(*args, **kwargs):
        do_something()
        try:
            return func(*args, **kwargs)
        finally:
            clean_up()
    return _mydecorator

# ... and with parameters
def mydecorator(param1, param2):
    def _mydecorator(func):
        @functools.wraps(func)
        def __mydecorator(*args, **kwargs):
            do_something(param1, param2)
            try:
                return func(*args, **kwargs)
            finally:
                clean_up()
        return __mydecorator
    return _mydecorator

(mi preferencia personal es crear decoradores mediante funciones, no clases)

El orden de decoradores es como sigue:


@d1
@d2
def func():
    pass

# is equivalent to
def func():
    pass

func = d1(d2(func))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top