我试图通过以下代码了解如何在一个函数上使用两个装饰器:
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
为什么当我同时调用两个包装函数时,它们都只执行其中之一?
答案 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)