Je souhaite construire des classes pour les utiliser comme décorateurs en respectant les principes suivants :
- Il devrait être possible d'empiler plusieurs décorateurs de classe de ce type sur une fonction.
- Le pointeur de nom de fonction qui en résulte ne devrait pas pouvoir être distingué de la même fonction sans décorateur, à l'exception peut-être du type ou de la classe dont il s'agit.
- Le fait de commander aux décorateurs ne devrait pas être pertinent, à moins que les décorateurs ne l'exigent. Par exemple, des décorateurs indépendants peuvent être appliqués dans n'importe quel ordre.
C'est pour un projet Django, et le cas spécifique sur lequel je travaille actuellement, la méthode a besoin de 2 décorateurs, et d'apparaître comme une fonction python normale :
@AccessCheck
@AutoTemplate
def view(request, item_id) {}
@AutoTemplate modifie la fonction de sorte qu'au lieu de renvoyer une réponse HttpResponse, elle renvoie simplement un dictionnaire à utiliser dans le contexte. Un RequestContext est utilisé et le nom du modèle est déduit du nom de la méthode et du module.
@AccessCheck ajoute des contrôles supplémentaires sur l'utilisateur en fonction de l'identifiant de l'article.
Je suppose qu'il s'agit simplement de faire en sorte que le constructeur soit correct et de copier les attributs appropriés, mais de quels attributs s'agit-il ?
Le décorateur suivant ne fonctionnera pas comme je l'ai décrit :
class NullDecl (object):
def __init__ (self, func):
self.func = func
def __call__ (self, * args):
return self.func (*args)
Comme le montre le code suivant :
@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));
En outre, essayez d'ajouter "print func. nom "dans le constructeur NullDecl, et cela fonctionnera pour le premier décorateur, mais pas pour le second - car le nom sera manquant.
Raffiné eduffy La réponse de l'auteur est un peu plus détaillée, et elle semble fonctionner assez 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