装饰器概要
本质:函数。
功能:装饰其他函数,即为其他函数增加其他功能。
原则:不修改被装饰函数的源代码;不修改被装饰函数的调用方法。
实现装饰器用到的知识:
1.函数即“变量”
2.高阶函数:♦把一个函数名当作实参传给另一个函数→可以实现不修改被装饰函数的源代码
♦返回值中包含函数名→可以实现不修改函数的调用方式
3.嵌套函数
接下来看一个例子
import time def test(): time.sleep(2) print("lucas") test()
运行结果:
lucas
Process finished with exit code 0
接下来我们采用装饰器给函数增加一个功能,看看该程序运行的时间:
import time def timer(func): #功能:定义一个deco函数,并返回deco的地址 def deco(*args,**kwargs): start_time = time.time() func() stop_time = time.time() print(stop_time-start_time) return deco @timer #相当于 test = timer(test) 即把deco的地址赋给test def test(): time.sleep(2) print("lucas") test() #此时test和deco指向同一地址,运行deco的函数体
运行结果:
lucas 2.0001139640808105 Process finished with exit code 0
实现了无参函数的装饰器。总结一下:
其实过程就相当于我们要执行test(),变成了执行deco()。如果test中带参数,也就相当于deco中带的参数,为了程序的可移植性,我们人为将deco中的参数定为*args,**kwargs。也就是可变长的参数。接下来我们看一下test中带参数的简单实例:
import time def timer(func): #功能:定义一个deco函数,并返回deco的地址 def deco(*args,**kwargs): #相当于test中的参数 start_time = time.time() func(*args,**kwargs) #相当于test中的参数 stop_time = time.time() print(stop_time-start_time) return deco @timer #相当于 test = timer(test) 即把deco的地址赋给test def test(name): time.sleep(2) print(name) test("lucas") #此时test和deco指向同一地址,运行deco的函数体
运行结果:
lucas 2.0001139640808105 Process finished with exit code 0
成功实现了修饰含参数的函数。
回头想一下,结合例子,只要记住如下的话:
定义timer函数,是为了保证被修饰的函数的调用方式不改变,即test调用方式不改变,仍为test()
定义deco函数,是为了保证在不改变被修饰函数(test)源代码的基础上,实现对其增加新功能(新增打印时间功能)。