Учитывая следующую украшенную (с аргументами) функцию, как я могу построить лямбда-функцию, которая возвращает функцию с различными аргументами? - PullRequest
0 голосов
/ 02 апреля 2020

Учитывая следующий декоратор с аргументами:

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

Есть ли более чистое решение?

...