Как только обработать *args и * * kwargs в decorator и оставить другие аргументы нетронутыми
Я хочу иметь декоратор, который принимает только *args
и **kwargs
в качестве входных данных, вносит в них некоторые изменения и затем вызывает исходную функцию с позиционными и именованными аргументами из оформленной функции без изменений.
Изменение аргументов состоит в том, чтобы просто добавить --
к args
, а также к ключам dict
из kwargs
.
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
в декораторе, не касаясь ни одного из позиционных и именованных аргументов декорированной функции и не потребляя их в *args
/**kwargs
-Аргументы моей декораторской функции?
1 ответ:
Вы можете попробовать проверить.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