Как использовать «двухслойный» декоратор без использования синтаксиса @? - PullRequest
0 голосов
/ 20 октября 2018

Скажем, у меня есть этот декоратор:

def decorator_with_args(decorator_arg1, decorator_arg2):                
    def decorator(func):
        def wrapped(*args, **kwargs):
            if decorator_arg1 == 'arg1' and decorator_arg2 == 'arg2':
                return func(*args, **kwargs)
        return wrapped
    return decorator

Обычно вы декорируете функцию следующим образом:

@decorator_with_args('arg1', 'arg2')
def function():
    return 'foo'

>>> foo = function()
'foo'

Как мне вызвать ее без использования синтаксиса @?

Я знаю, что если вы называете это, если это только однослойный декоратор (то есть декоратор без аргументов), то вы буквально оборачиваете его в функцию декоратора следующим образом:

>>> foo = decorator(function)
'foo'

Обратите внимание на function не называется.Как это будет работать, если и у декоратора, и у функции есть аргументы, которые нужно передать?

>>> foo = decorator_with_args(decorator(wrapped_function))

Но тогда куда деваются *args и **kwargs декоратора и исходной функции?

1 Ответ

0 голосов
/ 20 октября 2018

decorator_with_args() - это фабрика декораторов, то есть функция, которая возвращает декоратор.Это означает, что для того, чтобы использовать его без синтаксиса @, вам нужно вызвать его с его аргументами, а затем вызвать результат с вашей функцией в качестве аргумента.

Вот как это выглядит:

def function():
    return 'foo'

function = decorator_with_args('arg1', 'arg2')(function)

>>> function()
'foo'

Обратите внимание, что это аналогично разнице между использованием обычного декоратора с синтаксисом @ или без него:

@deco
def func(arg):
    # ...

соответствует

def func(arg):
    # ...

func = deco(func)

как

@deco_fac(x, y)
def func(arg):
    # ...

до

def func(arg):
    # ...

func = deco_fac(x, y)(func)
...