2010-09-16 39 views
13

给出一个函数:如何以编程方式更改python装饰器中的函数的argspec?

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

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

我怎样才能创建一个装饰,使得bare_argspec == decorated_argspec? (至于为什么,调用装饰函数的框架通过argspec检查来选择要传入的内容,所以装饰器必须保留相同的argspec才能发挥出色。当我在#python中提出这个问题时,我得到了一个关于为什么框架很糟糕的长篇演讲,这不是我正在寻找的东西;我必须在这里解决问题,而且我也只是对答案感兴趣)

+1

语法错误:无效的语法 - 我想你的意思'高清FUNC(...' – 2010-09-16 18:09:51

回答

12

Michele Simionato的decorator module有一个名为decorator的装饰器,它保留了函数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

functools.update_wrapper()和/或者functools.wraps()够好吗?

+6

都能跟得上,他们不保留argspec。 – 2010-09-16 19:39:59

2

还有的decorator模块:

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

这使得trace具有相同argspecs作为装饰功能的装饰。例如:

>>> @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)) 
相关问题