2010-09-16 19 views
13

Etant donnée une fonction:Comment modifier par programme l'argspec d'une fonction dans un décorateur python?

def func(f1, kw='default'): 
    pass 
bare_argspec = inspect.getargspec(func) 

@decorator 
def func2(f1, kw='default'): 
    pass 
decorated_argspec = inspect.getargspec(func2) 

Comment puis-je créer un décorateur tel que bare_argspec == decorated_argspec? Pour ce qui est de savoir pourquoi, le framework qui appelle la fonction décorée fait l'inspection argspec pour choisir ce qu'il faut passer, donc le décorateur doit conserver le même argspec pour pouvoir jouer au jeu. Quand j'ai posé cette question sur #python, J'ai eu un long discours sur les raisons pour lesquelles le cadre est nul, ce qui n'est pas ce que je cherche, je dois résoudre le problème ici aussi.)

+1

SyntaxError: invalide - Je pense que vous voulez dire 'def func (...' –

Répondre

12

Michele Simionato's decorator module a un décorateur appelé décorateur qui préserve les fonctions argspecs.

import inspect 
import decorator 

def func(f1, kw='default'): 
    pass 
bare_argspec = inspect.getargspec(func) 
print(bare_argspec) 
# ArgSpec(args=['f1', 'kw'], varargs=None, keywords=None, defaults=('default',)) 

@decorator.decorator 
def mydecorator(func,*args,**kw): 
    result=func(*args,**kw) 
    return result 

@mydecorator 
def func2(f1, kw='default'): 
    pass 
decorated_argspec = inspect.getargspec(func2) 
print(decorated_argspec) 
# ArgSpec(args=['f1', 'kw'], varargs=None, keywords=None, defaults=('default',)) 

assert(bare_argspec==decorated_argspec) 
0

Sont functools.update_wrapper() et/ou functools.wraps() assez bon?

+6

Non, ils ne conservent pas le argspec. –

2

Il y a le module decorator:

from decorator import decorator 
@decorator 
def trace(func, *args, **kw): 
    print 'calling', func, 'with', args, kw 
    return func(*args, **kw) 

Cela fait trace un décorateur avec les mêmes argspecs que la fonction décorée. Exemple:

>>> @trace 
... def f(x, y=1, z=2, *args, **kw): 
...  pass 

>>> f(0, 3) 
calling f with (0, 3, 2), {} 

>>> from inspect import getargspec 
>>> print getargspec(f) 
ArgSpec(args=['x', 'y', 'z'], varargs='args', keywords='kw', defaults=(1, 2))