【问题标题】:How to only process *args and **kwargs in decorator and leave other arguments untouched如何在装饰器中只处理 *args 和 **kwargs 而其他参数不受影响
【发布时间】:2018-04-05 11:09:12
【问题描述】:

我想要一个装饰器,它只接受 *args**kwargs 作为输入,对它们进行一些更改,然后调用原始函数,并使用装饰函数中的位置和命名参数保持不变。

对参数的更改只是将-- 添加到args 以及kwargsdict 的键之前。

例如我想像这样使用这个装饰器:

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-我的装饰函数的参数?

【问题讨论】:

  • 我还没有真正深入研究这些(12)是否包含您问题的确切解决方案,但至少它们是相关的并且可以提供一些有价值的见解。尤其值得一提的是decorator 模块。

标签: python-3.x decorator args keyword-argument


【解决方案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

但我很确定你不需要它。这种内省应该而且几乎总是可以避免的。

【讨论】:

  • 这个稍微调整的版本对我有用。如果有另一种“最佳实践”来执行此操作,我仍然会等待 1-2 天,正如您所说,几乎总是可以避免使用内省。如果没有更好的想法出现,我会接受你的回答并添加我所做的更改以使其与 python3 一起使用
  • 从检查包getargspec:This function is deprecated, as it does not support annotations or keyword-only parameters and will raise ValueError if either is present on the supplied callable.
猜你喜欢
  • 2014-04-26
  • 2018-08-28
  • 2013-09-25
  • 1970-01-01
  • 2023-03-20
  • 2020-12-09
  • 1970-01-01
  • 2021-08-19
  • 2016-04-20
相关资源
最近更新 更多