如何在不使用@语法的情况下使用“双层”装饰器?

时间:2018-10-20 18:26:27

标签: python python-3.x decorator wrapper

说我有这个装饰器:

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'

如何在不使用@语法的情况下调用它?

我知道,如果它只是一个单层装饰器(即不带args的装饰器),那么您调用它的方式就是您将它按如下方式包装在装饰器函数中:

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

请注意,不会调用function。如果装饰器和函数都具有需要传递的参数,怎么办?

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

但是装饰器的*args**kwargs和原始函数又去哪里了?

1 个答案:

答案 0 :(得分:3)

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)