Как я могу программно изменить аргумент функции в декораторе Python? - PullRequest
13 голосов
/ 16 сентября 2010

Для данной функции:

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, я получил длинную речь о том, почему фреймворк отстой, а это не то, что я ищу; Я должен решить проблему здесь. Кроме того, я просто заинтересован в ответе тоже)

Ответы [ 3 ]

12 голосов
/ 16 сентября 2010

Модуль декоратора Микеле Симионато имеет декоратор, называемый decorator, который сохраняет аргументы функции.

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 голосов
/ 16 сентября 2010

Модуль :

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))
0 голосов
/ 16 сентября 2010

Достаточно ли хороши functools.update_wrapper() и / или functools.wraps()?

...