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:
- Debería ser posible apilar varios decoradores de clase de este en la parte superior de la función 1.
- 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.
- 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