qué patron parametros ejemplo decoradores decorador con python decorator

parametros - patron decorator python



Clases de decorador en Python (3)

El módulo decorador lo ayuda a escribir decoradores que preservan sus firmas.

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

Quiero construir clases para usar como decoradores con los siguientes principios intactos:

  1. Debería ser posible apilar varios decoradores de clase de este en la parte superior de la función 1.
  2. El puntero del nombre de la función resultante debe ser indistinguible de la misma función sin un decorador, excepto tal vez para qué tipo / clase es.
  3. Ordenar a los decoradores no debería ser relevante a menos que así lo hayan ordenado los decoradores. Es decir. decoradores independientes podrían ser aplicados en cualquier orden.

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

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

@AutoTemplate cambia la función para que en lugar de devolver un HttpResponse, simplemente devuelva un diccionario para usar en el contexto. Se utiliza un RequestContext y el nombre de la plantilla se deduce del nombre y el módulo del método.

@AccessCheck agrega controles adicionales en el usuario en función del item_id.

Supongo que es solo para obtener el constructor correcto y copiar los atributos apropiados, pero ¿qué atributos son estos?

El siguiente decorador no funcionará como lo describo:

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

Como lo demuestra 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, intente agregar "print func. Name" en el constructor NullDecl, y funcionará para el primer decorador, pero no el segundo, ya que faltará el nombre.

La respuesta de Eduffy refinada un poco, y parece funcionar 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


Para crear un decorador que ajuste las funciones en un asunto que las haga 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 usando funciones, no clases)

El orden de los decoradores es el siguiente:

@d1 @d2 def func(): pass # is equivalent to def func(): pass func = d1(d2(func))


Una clase de decorador sin 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 luego puedes aplicarlo normalmente:

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