如何在装饰器中仅处理 *args 和 **kwargs 并保持其他参数不变
How to only process *args and **kwargs in decorator and leave other arguments untouched
我想要一个装饰器,它只需要 *args
和 **kwargs
作为输入,对它们进行一些更改,然后使用装饰函数中的位置和命名参数调用原始函数不变.
对参数的更改只是将 --
添加到 args
以及 kwargs
的 dict
的键之前。
例如我想像这样使用这个装饰器:
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
此处pos1
、pos2
和named1
应该被装饰器忽略。
所以像这样调用 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
,而不触及装饰函数的任何位置参数和命名参数,并且没有在我的 Decorator 函数的 *args
/**kwargs
-Arguments 中消耗那些?
您可以试试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
但我很确定您不需要它。这种自省应该而且几乎总是可以避免的。
我想要一个装饰器,它只需要 *args
和 **kwargs
作为输入,对它们进行一些更改,然后使用装饰函数中的位置和命名参数调用原始函数不变.
对参数的更改只是将 --
添加到 args
以及 kwargs
的 dict
的键之前。
例如我想像这样使用这个装饰器:
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
此处pos1
、pos2
和named1
应该被装饰器忽略。
所以像这样调用 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
,而不触及装饰函数的任何位置参数和命名参数,并且没有在我的 Decorator 函数的 *args
/**kwargs
-Arguments 中消耗那些?
您可以试试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
但我很确定您不需要它。这种自省应该而且几乎总是可以避免的。