代码之家  ›  专栏  ›  技术社区  ›  Chris R

如何以编程方式更改Python装饰器中函数的argspec?

  •  13
  • Chris R  · 技术社区  · 14 年前

    给定函数:

    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 ?

    (至于原因,调用decorated函数的框架执行argspec检查以选择要传递的内容,因此decorator必须保留相同的argspec才能发挥作用。当我在python上提出这个问题时,我做了一个长篇演讲,讨论了为什么框架很糟糕,这不是我要找的;我必须在这里解决这个问题。另外,我对答案也很感兴趣)

    3 回复  |  直到 14 年前
        1
  •  12
  •   unutbu    14 年前

    Michele Simionato的 decorator module 有一个名为decorator的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)
    
        2
  •  2
  •   nosklo    14 年前

    这里有 decorator 模块:

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

    这使得 trace 与修饰函数具有相同参数规格的修饰器。例子:

    >>> @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))
    
        3
  •  0
  •   llasram    14 年前

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