C'est ce que je veux faire:Est-il possible d'utiliser la réflexion pour examiner les décorateurs d'une fonction dans Python 2.5?
@MyDecorator
def f():
pass
for d in f.decorators:
print d
C'est ce que je veux faire:Est-il possible d'utiliser la réflexion pour examiner les décorateurs d'une fonction dans Python 2.5?
@MyDecorator
def f():
pass
for d in f.decorators:
print d
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
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.
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é. –