多层装饰器例子
def outter1(func1): print('加载了outter1') def wrapperl(*args,**kwargs): print('执行了wrapperl') res1=func1(*args,**kwargs) return res1 return wrapperl def outter2(func2): print('加载了outter2') def wrapper2(*args,**kwargs): print('执行了wrapper2') res2=func2() return res2 return wrapper2 def outter3(func3): print('加载了outter3') def wrapper3(*args,**kwargs): print('执行了wrapper3') res3=func3(*args,**kwargs) return res3 return wrapper3 @outter1 @outter2 @outter3 def index(): print('from index') index()
分析调用过程
@outter1 # index = outter1(wrapper2) @outter2 # wrapper2 = outter2(wrapper3) @outter3 # wrapper3 = outter3(最原始的index函数地址) def index(): print('from index') # @outter3紧贴index(),所以此时outter3调用的是index(),而返回的实际上是wrapper3,所以wrapper3 = outter3(index).(这里传入的是最原始的index函数内存地址) # @outter3的调用完之后,这时@outter2看到的是wrapper3,所以这时outter2调用的就是wrapper3,而返回的是wrapper2,所以有 wrapper2 = outter2(wrapper3) # 同理,当@outter2调用完之后,@outter1看到的就是wrapper2,所以outter1这时调用的就是wrapper2,因为outter1的上层没有语法糖继续调用,所以这里就给它起名和被装饰函数同名,也就是index,所以有index = outter1(wrapper2) # 根据上面的例子中,调用wrapper3、wrapper2、wrapper1之前会打印一句话,于是,根据我们推理的加载顺序,在没有调用index()时它打印的顺序就是 """ 加载了outter3 加载了outter2 加载了outter1 """
分析完调用顺序后我们来看它的运行顺序
def outter1(func1): print('加载了outter1') def wrapper1(*args,**kwargs): # 根据上面的推导结果,我们调用index()实际上就是调用wrapper1 print('执行了wrapperl') # 调用wrapper1时首先打印这句话 res1=func1(*args,**kwargs) # 然后执行到这一步需要调用func1,而func1实际上是在推导过程中outter1括号中的wrapper2, return res1 return wrapper1 def outter2(func2): print('加载了outter2') def wrapper2(*args,**kwargs): # 于是来执行wrapper2 print('执行了wrapper2') # 执行wrapper2时打印这句话 res2=func2() # 然后执行到这一步需要调用func2,func2与上面的func1同理,所以在这里它就是调用wrapper3 return res2 return wrapper2 def outter3(func3): print('加载了outter3') def wrapper3(*args,**kwargs): # 然后接着执行了wrapper3, print('执行了wrapper3') # 执行wraper3时打印这句话 res3=func3(*args,**kwargs) # 然后到了这一步要调用func3,于是执行func3,而根据之前推导的结果我们知道,func3其实就是outter3括号中的index return res3 return wrapper3 @outter1 @outter2 @outter3 def index(): # 执行index函数 print('from index') # 打印这句话 index() #根据执行过成我们可以得到,执行过程中打印的三句话是这样的: """ 执行了wrapperl 执行了wrapper2 执行了wrapper3 """
然后我们来看最终的执行结果
小结:多层装饰器在装饰的时候,它的顺序是由下往上,而在执行的时候,它的顺序由上到下。