Аргументированная функция декоратора Python - PullRequest
1 голос
/ 04 апреля 2019

У меня есть этот пример:

def decorator_function_with_arguments(arg1, arg2, arg3):
    def wrap(f):
        print("Inside wrap")
        def wrapped_f(*args):
            print("Pre")
            print("Decorator arguments:", arg1, arg2, arg3)
            f(*args)
            print("Post")
        return wrapped_f
    return wrap

@decorator_function_with_arguments("hello", "world", 42)
def sayHello(a1, a2, a3, a4):
    print('sayHello arguments:', a1, a2, a3, a4)

sayHello("say", "hello", "argument", "list")

Вывод:

Inside wrap Pre Decorator arguments: hello world 42 sayHello arguments: say hello argument list Post

Я интерпретирую это следующим образом: decorator_function_with_arguments получает свои 3 аргумента. Он выводит функцию (wrap), которая получает функцию, и выводит функцию, которая является целью украшения. Так что теперь wrap будет выполнено (печатается «Внутренняя упаковка»), происходит декорирование, wrap берет sayHello и помещает его в wrapped_f, мы возвращаемся. Теперь, если я позвоню sayHello, это будет завернутая версия, поэтому все остальное будет распечатано. Хорошо, но теперь, если я напишу это:

def argumented_decor(dec_arg1):
    def actual_decor(old_func):
        print("Pre Wrapped")
        def wrapped():
            print("Pre Main")
            print(dec_arg1)
            old_func()
            print("Post Main")
        return actual_decor
    return actual_decor

@argumented_decor("Decor Argument")
def f2():
    print("Main")

f2()

При звонке f2 я получаю сообщение об ошибке: TypeError: actual_decor() missing 1 required positional argument: 'old_func'

Почему? argumented_decor получает аргумент, actual_decor будет выполнено, «Pre Wrapped» будет напечатано, f2 будет упаковано. Теперь, если я его вызываю, он должен выполнять самую внутреннюю функцию wrapped. Почему бы и нет? Я надеюсь, что мог бы задать свой вопрос по понятным причинам. Спасибо!

1 Ответ

2 голосов
/ 04 апреля 2019

Ваша actual_decor функция возвращает себя, когда должна вернуть функцию-оболочку wrapped:

def argumented_decor(dec_arg1):
    def actual_decor(old_func):
        print("Pre Wrapped")
        def wrapped():
            print("Pre Main")
            print(dec_arg1)
            old_func()
            print("Post Main")
        return wrapped
    return actual_decor
...