简体   繁体   English

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

[英]How can I programmatically change the argspec of a function in a python decorator?

Given a function: 给定一个功能:

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

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

How can I create a decorator such that bare_argspec == decorated_argspec ? 如何创建一个装饰器,使bare_argspec == decorated_argspec

(As to why, the framework that calls the decorated function does argspec inspection to choose what to pass in, so the decorator has to retain the same argspec in order to play nice. When I posed this question on #python, I got a long speech about why the framework sucks, which is not what I'm looking for; I have to solve the problem here. Also, I'm just interested in the answer, too) (至于为什么,调用装饰函数的框架会进行argspec检查以选择要传入的内容,因此装饰器必须保留相同的argspec才能发挥出色。当我在#python上提出这个问题时,我得到了一个长的关于为什么框架糟糕的演讲,这不是我正在寻找的;我必须在这里解决问题。另外,我也只是对答案感兴趣)

Michele Simionato's decorator module has a decorator called decorator which preserves function argspecs. Michele Simionato的装饰模块有一个名为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)

There's the decorator module: 装饰模块:

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

That makes trace a decorator with the same argspecs as the decorated function. 这使得trace装饰器具有与装饰函数相同的argspecs。 Example: 例:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM