如何只在装饰器中处理* args和** kwargs并保持其他参数不受影响

时间:2017-10-24 15:14:34

标签: python-3.x decorator args kwargs

我希望有一个装饰器,只需要*args**kwargs作为输入,对它们进行一些更改,然后使用装饰函数中的位置和命名参数调用原始函数。< / p>

对参数的更改只是将--添加到args以及dict kwargs的键。

E.g。我想像这样使用这个装饰器:

from decorator import decorator

@decorator
def prepare_opts(decorated_func, *args, **kwargs):
    prepared_args = prepare_single_opt_keys(args)
    prepared_kwargs = prepare_named_opt_keys(kwargs)

    return decorated_func(*prepared_args, **prepared_kwargs)

@my_decorator
def func1(pos1, pos2, *args, named1=None, **kwargs):
    ...do stuff

此处pos1pos2named1应该被装饰者忽略。

这样打电话给func1

func1('foo', 'bar', 'foo', 'bar', named1='foobar', foo='bar')

应该像这样调用装饰函数:

func1('foo', 'bar', named1='foobar', ('--foo', '--bar'), {'--foo': 'bar'})

但是这显然不起作用,因为装饰器将('--foo', '--bar', '--foo', '--bar')传递给pos1{'--named1': 'foobar', '--foo': 'bar'}传递给pos2

我知道如果我将装饰器改为:

,我可以得到正确的参数
@decorator
def prepare_opts(decorated_func, pos1, pos2, *args, named1, **kwargs):
    prepared_args = prepare_single_opt_keys(args)
    prepared_kwargs = prepare_named_opt_keys(kwargs)

    return decorated_func(pos1, pos2, *prepared_args, named1, **prepared_kwargs)

但问题在于,我希望装饰器能够处理许多不同的函数,它们都具有不同数量的位置和命名参数以及额外的*args**kwargs

我的问题摘要:有没有办法解析装饰器中的*args**kwargs,而不会触及装饰函数的任何位置和命名参数,也不会消耗*args / **kwargs - 我的装饰师功能的论点?

1 个答案:

答案 0 :(得分:1)

您可以尝试inspect.getargspec功能。我没有测试它,但你可以使用这种方法。

import inspect

def your_decorator(func):
    func_args = inspect.getargspec(func)[0]
    args_number = len(func_args)

    def wrapper(*args, **kwargs):
        if len(args) > args_number:
            args[args_number:] = prepare_single_opt_keys(args[args_number:])
        optional_kwargs = {k: kwargs.pop(k) for k in kwargs if k not in func_args}
        prepared_kwargs = prepare_named_opt_keys(optional_kwargs)
        kwargs.update(prepared_kwargs)
        return func(*args, **kwargs)
    return wrapper

但我很确定你不需要它。这种反省应该而且几乎总能避免。