Учитывая следующий декоратор с аргументами:
def infrastructure(
order: int = 0,
enabled: bool = True,
only_on_env: str= None,
isolated: bool = False,
):
def real_decorator(func):
func.meta_data = InfrastructureMeta(
order=order,
enabled=enabled,
only_on_env=only_on_env,
isolated=isolated,
name=func.__name__,
)
@wraps(func)
def wrapper(*args, **kwargs):
func(*args, **kwargs)
return wrapper
return real_decorator
Как я могу использовать лямбда-функцию для получения ссылок на фиктивную функцию, используя этот декоратор? Я пробовал следующее безрезультатно:
dummy = infrastructure(lambda: print('dummy'))
Это кажется тривиальным на стандартном декораторе, но немного сложнее с вложенными декораторами / аргументами. Я хочу иметь возможность создавать функции «dynamici c», которые я могу использовать для тестирования. В настоящее время проблема заключается в том, что все функции, которые я создаю, имеют одну и ту же ссылку, мне нужны новые, так как я переопределяю некоторые атрибуты функции (пользовательские):
@infrastructure()
def dummy():
pass
def build_dummy(
order: int = None,
enabled: bool = None,
only_on_env: str = None,
isolated: bool = None,
):
fx = dummy
if order is not None:
fx.meta_data.order = order
if enabled is not None:
fx.meta_data.enabled = enabled
if only_on_env is not None:
fx.meta_data.only_on_env = only_on_env
if isolated is not None:
fx.meta_data.isolated = isolated
return fx
Все мои функции.meta_data.order равны 3 в этот экземпляр (просто меняя тот же указатель):
fxs = [build_dummy(isolated=True, order=n) for n in range(1, 4)] # ideally these would be 1->3 individually
Я пробовал copy.deepcopy (пустышка), но также безрезультатно, я не думаю, что это так просто
best Я могу найти решение:
def copy_func(f):
fn = types.FunctionType(
f.__code__, f.__globals__, f.__name__, f.__defaults__, f.__closure__
)
# in case f was given attrs (note this dict is a shallow copy):
fn.__dict__ = copy.deepcopy(f.__dict__)
return fn
Есть ли более чистое решение?