【问题标题】:How can I programmatically change the argspec of a function in a python decorator?如何以编程方式更改 python 装饰器中函数的 argspec?
【发布时间】:2011-04-13 08:43:56
【问题描述】:

给定一个函数:

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上提出这个问题时,我关于框架为什么糟糕的长篇演讲,这不是我想要的;我必须在这里解决问题。另外,我也只是对答案感兴趣)

【问题讨论】:

  • SyntaxError: invalid syntax - 我想你的意思是def func(...

标签: python reflection decorator inspect


【解决方案1】:

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))

【讨论】:

    【解决方案2】:

    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)
    

    【讨论】:

      【解决方案3】:

      functools.update_wrapper() 和/或 functools.wraps() 是否足够好?

      【讨论】:

      • 不;他们不保留 argspec。
      猜你喜欢
      • 2016-03-08
      • 1970-01-01
      • 2022-10-18
      • 1970-01-01
      • 2018-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-17
      相关资源
      最近更新 更多