2010-10-14 1 views

Répondre

3

Ceci est généralement pas possible sans la coopération des décorateurs. Par exemple,

def my_decorator(f): 
    def wrapper(*args, **kwargs): 
     return f(*args, **kwargs) 
    wrapper.decorators = [wrapper] 
    if hasattr(f, 'decorators'): 
     wrapper.decorators.extend[f.decorators] 
    return wrapper 

Essentiellement, tout le décorateur n'est envelopper la fonction comme d'habitude, puis mettre un décorateurs attribut sur la fonction enveloppe. Il vérifie ensuite la fonction enveloppée pour une liste similaire et la propage vers le haut.

C'est assez inutile si

Ce que je pense que vous voulez est

def my_decorator(f): 
     def wrapper(args): 
      return f(args) 
     wrapper.decorated = f 
     return wrapper 

Cela vous permettra de faire des choses comme

@my_other_decorator # another decorator following the same pattern 
@my_decorator 
def foo(args): 
    print args 

foo.decorated(args) # calls the function with the inner decorated function (my_decorator) 
foo.decorated.decorated(args) # original function 

Vous pouvez réellement abstraite ce modèle en un décorateur

def reversable(decorator): 
    def wrapper(func): 
     ret = decorator(func) # manually apply the decorator 
     ret.decorated = funC# save the original function 
     return ret 
    return wrapper 

Maintenant, quand vous écrivez votre décorateur:

@reversable 
def my_decorator(f): 
    def wrapper(x): 
     return f(x + 1) 
    return wrapper 
+0

Notez que 'functools.wraps' de Python 3.2 utilise le nom' __wrapped__' pour pointer vers la fonction d'origine. Je recommande d'utiliser le même nom, de sorte que le code peut cesser de diverger sur ce point. (J'ai besoin de commencer à faire ça aussi, j'ai toujours utilisé le nom "func".) Je recommande d'utiliser 'functools.wraps', mais ce n'est pas vraiment une solution tant que le 3.2 n'est pas vraiment utilisé. –

1

La syntaxe @MyDecorator est simplement un raccourci pour écrire le code Python suivant:

def f(): 
    pass 
f = MyDecorator(f) 

écrit dans ce formulaire, vous pouvez voir que les décorateurs appliqué à la fonction ne sont pas tenus en aucun cas. Faites en sorte que vos décorateurs se souviennent quand ils sont appliqués (Aaron's answer a quelques bonnes idées sur la façon de le faire), mais vous devriez envelopper tous les décorateurs de tierce partie avec les vôtres.

Questions connexes