装饰器是对已有的模块进行装饰(添加新功能)的函数。
现有一段代码:
1 import time 2 def func1(): 3 time.sleep(3) 4 print("in the func1") 5 def func2(): 6 time.sleep(2) 7 print("in the func2") 8 func1() 9 func2()
现在需要增加func1和func2的功能,计算段代码的运行时间。
思路1:修改函数内的代码:
1 import time 2 def func1(): 3 start_time = time.time() 4 time.sleep(3) 5 print("in the func1") 6 stop_time = time.time() 7 print("this program run %ss"%(stop_time-start_time)) 8 def func2(): 9 start_time = time.time() 10 time.sleep(2) 11 print("in the func2") 12 stop_time = time.time() 13 print("this program run %ss"%(stop_time-start_time)) 14 func1() 15 func2()
每个函数都添加了红色的代码段,如果需要改的func较多时,该方法明显不适用。并且违反了为函数添加附加功能时的原则1:不能修改被装饰函数的源代码。
思路2:增加新函数:
1 import time 2 def func1(): 3 time.sleep(3) 4 print("in the func1") 5 def func2(): 6 time.sleep(2) 7 print("in the func2") 8 def func_new1(): 9 start_time = time.time() 10 func1() 11 stop_time =time.time() 12 print("this program run %ss"%(stop_time-start_time)) 13 def func_new2(): 14 start_time = time.time() 15 func2() 16 stop_time =time.time() 17 print("this program run %ss"%(stop_time-start_time)) 18 func_new1() 19 func_new2()
该方法增加了新函数,将原有函数引用至新函数中。但问题又来了,需要改主程序中对原有函数的引用方法,违反了并且违反了为函数添加附加功能时的原则2:不能修改被装饰函数的调用方式。
此刻,我们需要新的知识储备来完善对装饰器的理解
1.函数的嵌套
2.高阶函数
3.函数——变量的关系
高阶函数+嵌套函数===》装饰器
插入名词的解释!!
高阶函数:满足下列原则之一的就是高阶函数:
a.把一个函数名当作实参传给另一个函数的函数。
1 import time 2 def bar(): 3 time.sleep(3) 4 print("in the bar") 5 def test(func): 6 start_time = time.time() 7 func() 8 stop_time = time.time() 9 print("the func run time is %s"%(stop_time-start_time)) 10 test(bar)
在此函数中,bar作为实参被传递给形参func,test(bar)。通过test()函数为bar()增加了新功能,且没有改变bar()的源代码。但改变了原有bar()的调用方式。
实现了不修改被装饰函数的源代码情况下为其添加新功能的目的。
b.返回值中包含函数名
1 import time 2 def bar(): 3 time.sleep(3) 4 print("in the bar") 5 def test(func): 6 print(func) 7 print() 8 return func 9 bar = test(bar) 10 bar()
在此代码中,原有函数bar(),然后bar作为函数名被传给新增函数test(),随后又作为该函数的返回值。相当与给bar()增加了新的功能(显示bar()的内存地址),但没有改变bar()的调用方式。
嵌套函数:在函数体内声明的函数(必须是声明,不能是调用)
def test1(): print("in the test1") def test2(): print("in the test2") test2() test1()
test2()是在test1()中声明的函数
将高阶函数与嵌套函数结合,
1 import time 2 def timmer(func): 3 def deco(): 4 start_time = time.time() 5 func() 6 stop_time = time.time() 7 print("the func run time is %ss"%(stop_time-start_time)) 8 return deco 9 @timmer #等于在func1被调用前加上func1=timmer(func1) 10 def func1(): 11 time.sleep(3) 12 print("in the func1") 13 @timmer 14 def func2(): 15 time.sleep(2) 16 print("in the func2") 17 func1() 18 func2()
其中@timmer = func1= timmer(func1),就是在被装饰的函数前加上装饰器的名称。在没有改变被装饰代码的源代码及调用方式的情况下增加了其功能。