Как только обработать *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