How can I programmatically change the argspec of a

2019-01-15 17:53发布

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?

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

3条回答
Evening l夕情丶
2楼-- · 2019-01-15 18:36

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. 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))
查看更多
老娘就宠你
3楼-- · 2019-01-15 18:49

Michele Simionato's decorator module has a decorator called decorator which preserves function 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)
查看更多
一纸荒年 Trace。
4楼-- · 2019-01-15 18:53

Are functools.update_wrapper() and/or functools.wraps() good enough?

查看更多
登录 后发表回答