双重装饰器,为什么我的封闭函数之一没有执行?

时间:2018-10-08 07:09:59

标签: python decorator

我试图通过以下代码了解如何在一个函数上使用两个装饰器:

def fxn(func):
    print("fxn_outer 1")
    def fxn_inner(*args, **kwargs):
        print("fxn_inner 1")
    return fxn_inner

def fxn2(func):
    print("fxn_outer 2")
    def fxn_inner2(*args, **kwargs):
        print("fxn_inner 2")
    return fxn_inner2

@fxn
@fxn2
def fxn3 (a, b):
    print(a + b)

fxn3(1, 2)

我对为什么在上面的代码中执行fxn_inner感到困惑,而对fxn_inner2却没有执行。

输出为:

fxn_outer 2
fxn_outer 1
fxn_inner 1

当我期望以下输出时:

fxn_outer 2
fxn_outer 1
fxn_inner 1
fxn_inner 2

为什么当我同时调用两个包装函数时,它们都只执行其中之一?

2 个答案:

答案 0 :(得分:4)

装饰器只是用于调用函数并重新分配名称的语法糖,所以您所做的等同于此:

fxn3 = fxn2(fxn3)
fxn3 = fxn(fxn3)

fxn3(1, 2)

那是怎么回事?第一次分配后,您将拥有fxn3 == fxn2_inner。 在第二行之后有fxn3 == fxn_inner

但是fxn(和fxn_inner)的定义只是丢弃了参数func!因此,当您致电fxn3(1,2) == fxn_inner(1, 2)时,您看不到它被呼叫。

如果要调用原始函数,则应在func函数内部调用*_inner

def fxn(func):
    print("fxn_outer 1")
    def fxn_inner(*args, **kwargs):
        print("fxn_inner 1")
        return func(*args, **kwargs)
    return fxn_inner

def fxn2(func):
    print("fxn_outer 2")
    def fxn_inner2(*args, **kwargs):
        print("fxn_inner 2")
        return func(*args, **kwargs)
    return fxn_inner2

答案 1 :(得分:1)

那是因为您没有执行在装饰器主体中赋予装饰器的功能(包装函数)。因此,执行在第一个装饰器(即fxn_inner)的主体中停止。

通常,您对装饰器的作用是调用(调用)装饰器中的装饰函数,即

def fxn(func):
    print("fxn_outer 1")
    def fxn_inner(*args, **kwargs):
        print("fxn_inner 1")
        func(*args, **kwargs)
    return fxn_inner

def fxn2(func):
    print("fxn_outer 2")
    def fxn_inner2(*args, **kwargs):
        print("fxn_inner 2")
        func(*args, **kwargs)
    return fxn_inner2

@fxn
@fxn2
def fxn3 (a, b):
    print(a + b)

fxn3(1, 2)