#python #decorator #python-decorators
Вопрос:
Я пытаюсь создать два очень похожих декоратора, каждый из которых принимает общие args
и kwargs
, и оба из которых внутренне разделяют код. Единственное различие между их двумя определениями заключается в значении определенного флага (который не предоставляется пользователю). Полный контекст содержится в этом вопросе.
В настоящее время у меня есть первый декоратор, определенный (без ссылки на флаг) как
import functools
def decorator_factory(*args_units, **kwargs_units):
def _decorator(func):
@functools.wraps(func)
def _wrapper(*args, **kwargs):
return f(*args, **kwargs, *args_units, **kwargs_units)
return _wrapper
return _decorator
который можно использовать следующим образом
@decorator_factory(*args_units, **kwargs_units)
def func_to_be_decorated(*args, **kwargs):
...
Вместо этого я хочу создать двух очень похожих декораторов, что-то вроде этого
def decorator_factory1(*args_units, **kwargs_units):
return functools.partial(_decorator, flag=True)
def decorator_factory2(*args_units, **kwargs_units):
return functools.partial(_decorator, flag=False)
def _decorator(func, flag):
@functools.wraps(func)
def _wrapper(*args, **kwargs):
if flag:
return f1(*args, **kwargs, *args_units, **kwargs_units)
else:
return f2(*args, **kwargs, *args_units, **kwargs_units)
return _wrapper
который затем можно было бы использовать следующим образом
@decorator_factory1(*args_units, **kwargs_units)
def func1_to_be_decorated(*args, **kwargs):
...
@decorator_factory2(*args_units, **kwargs_units)
def func2_to_be_decorated(*args, **kwargs):
...
Проблема в том , что этот шаблон не передается *args_units
и **kwargs_units
, поскольку они больше недоступны в локальном пространстве имен внутри _decorator
функции.
Комментарии:
1. где определены
f
,f1
,f2
?2. какую ошибку вы получаете, когда используете этот способ
f1(*args, **kwargs, *args_units, **kwargs_units)
? кстати, вам нужно передать параметр в следующем порядкеf1(*args, *args_units, **kwargs, **kwargs_units)
3. вы можете объединить два декоратора
decorator_factory1 amp; 2
в один, параметризовав атрибутflag
как, например, smt какclass Dec: def __init__(self, flag): self.flag = flag ; def decorator_factory(self, *args_units, **kwargs_units): return functools.partial(_decorator, flag=self.flag)
и назвать его как@Dec(True).decorator_factory(...)
… просто идея4. … и чтобы устранить
*args, **kwargs, *args_units, **kwargs_units
проблему, вы могли бы выполнить вложенныйfunctools.partial
вызов, в котором в каждом вызове вы передаете другое «семейство» аргументов.5. Где/когда вы ожидаете, что фактические значения
**args_units
и**kwargs_units
будут получены в@
строке ? Декоратор выполняется во время компиляции, поэтому там нет значений, если только у вас нет этих двух в глобальных переменных.