这篇文章中记录说明下多个装饰器一同装饰同一个函数时的执行顺序问题。
【装饰器链】
按照惯例,先看代码示例:
import time def debug1(str): #传参接受类的方法 def func11(f1): def func12(my,m,n): #原类方法有三个参数,故内层函数需要传递相同的参数 print("\n\rStarting debug1()\n\r") f1(my,m,n) print("\n\rStopped debug1()\n\r") return func12 #返回内层函数 return func11 def debug2(num): #传参接受类的方法 def func21(f2): def func22(my,m,n): #原类方法有三个参数,故内层函数需要传递相同的参数 print("\n\rStarting debug2()\n\r") time.sleep(num) f2(my,m,n) print("\n\rStopped debug2()\n\r") return func22 #返回内层函数 return func21 class test(): @debug2(3) #sleep N秒后再执行 @debug1("Steve Jobs") #打印此次的执行人员 def myAdd(self,a,b): print(a + b) if __name__ == "__main__": myIns=test() myIns.myAdd(2,3)
其执行结果如下:
结果就像三明治夹心一样:最顶、最底都为debug2的输出,次顶、次底都为debug1的输出,最中间的夹心为myAdd的输出。
为什么是这个样子呢?结合前两篇的介绍我们容易得知,这种简写的方式其实质是下面这种调用关系:
import time def debug1(str): #传参接受类的方法 def func11(f1): def func12(my,m,n): #原类方法有三个参数,故内层函数需要传递相同的参数 print("\n\rStarting debug1()\n\r") f1(my,m,n) print("\n\rStopped debug1()\n\r") return func12 #返回内层函数 return func11 def debug2(num): #传参接受类的方法 def func21(f2): def func22(my,m,n): #原类方法有三个参数,故内层函数需要传递相同的参数 print("\n\rStarting debug2()\n\r") time.sleep(num) f2(my,m,n) print("\n\rStopped debug2()\n\r") return func22 #返回内层函数 return func21 class test(): #@debug2(3) #sleep N秒后再执行 #@debug1("Steve Jobs") #打印此次的执行人员 def myAdd(self,a,b): print(a + b) #上面两行的简写格式,其实质是下面这种调用关系: func21=debug2(3) #因为装饰器带有参数,实际上就是函数调用,需要先执行 func11=debug1("Steve Jobs") #因为装饰器带有参数,实际上就是函数调用,需要先执行 myAdd=func11(myAdd) #此处得到的myAdd实质就是func12 myAdd=func21(myAdd) #此处得到的myAdd实质就是func22 if __name__ == "__main__": myIns=test() myIns.myAdd(2,3) #此时调用的其实是func22(2,3)
其执行结果如下(跟上面的简写形式结果一致,进一步验证了我们的拆分是等价的):
通过上述实验证明:多个装饰器同时装饰一个函数的时候,调用的原则是:由近及远。
原文:https://www.cnblogs.com/lucky815/p/14534262.html