一、什么是装饰器
装饰器本质就是函数,功能是为其他函数附加功能
二、装饰器遵循的原则
1、不修改被修饰函数的源代码
2、不修改被修饰函数的调用方式
三、实现装饰器的知识储备
装饰器=高阶函数+函数嵌套+闭包
示例1: 用函数实现
1 #计算从1-100,统计函数运行时间 2 3 import time 4 def cal(l): 5 start_time=time.time() 6 res=0 7 for i in l: 8 time.sleep(0.1) 9 res+=i 10 stop_time = time.time() 11 print('函数的运行时间是%s' %(stop_time-start_time)) 12 return res 13 14 print(cal(range(100))) #直接打印得到运行的时间
执行结果:
1 函数的运行时间是10.007169723510742 2 4950
示例2:用装饰器实现函数运行时间
1 import time 2 def timmer(func): 3 def wrapper(*args,**kwargs): 4 start_time=time.time() 5 res=func(*args,**kwargs) 6 stop_time = time.time() 7 print('函数运行时间是%s' %(stop_time-start_time)) 8 return res 9 return wrapper 10 11 @timmer #调用装饰器 12 def cal(l): 13 res=0 14 for i in l: 15 time.sleep(0.1) 16 res+=i 17 return res 18 19 res=cal(range(20)) 20 print(res)
四、高阶函数高阶函数定义
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
3.满足上述条件任意一个,都可称之为高阶函数
高阶函数示例如下:
示例1:函数接收的参数是一个函数名
1 #1.函数接收的参数是一个函数名 2 import time 3 def foo(): 4 time.sleep(3) 5 print('你好啊林师傅') 6 7 def test(func): #test高阶函数 8 # print(func) #获取到内存地址 9 start_time=time.time() 10 func() 11 stop_time = time.time() 12 print('函数运行时间是 %s' % (stop_time-start_time)) 13 # foo() 14 test(foo)
执行结果:
1 你好啊林师傅 2 函数运行时间是 3.0003013610839844 3 来自foo
示例2:
1 def foo(): 2 print('from the foo') 3 def test(func): 4 return func 5 6 # res=test(foo) 7 # # print(res) 8 # res() 9 10 foo=test(foo) 11 # # print(res) 12 foo() 13 14 import time 15 def foo(): 16 time.sleep(3) 17 print('来自foo') 18 19 #不修改foo源代码 20 #不修改foo调用方式
示例3:
1 #多运行了一次,不合格 2 import time 3 def foo(): 4 time.sleep(3) 5 print('来自foo') 6 7 def timer(func): 8 start_time=time.time() 9 func() 10 stop_time = time.time() 11 print('函数运行时间是 %s' % (stop_time-start_time)) 12 return func 13 foo=timer(foo) 14 foo()
示例4:
1 #没有修改被修饰函数的源代码,也没有修改被修饰函数的调用方式,但是也没有为被修饰函数添加新功能 2 import time 3 def foo(): 4 time.sleep(3) 5 print('来自foo') 6 7 def timer(func): 8 start_time=time.time() 9 return func 10 stop_time = time.time() 11 print('函数运行时间是 %s' % (stop_time-start_time)) 12 13 foo=timer(foo) 14 foo()
执行结果:
1 来自foo
结论:高阶函数,满足不了装饰器的功能。
高阶函数总结:
1.函数接收的参数是一个函数名
作用:在不修改函数源代码的前提下,为函数添加新功能,
不足:会改变函数的调用方式
2.函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:不能添加新功能
五、函数的嵌套
1、什么是函数的嵌套?
通过在函数内部def的关键字再声明一个函数即为嵌套
示例:
1 def father(name): 2 def son(): 3 print('我的爸爸是%s' %name) 4 def grandson(): 5 name='就是我自己' 6 print('我的爷爷是%s' %name) 7 grandson() 8 son() 9 father('linhaifeng')
执行结果:
1 我的爸爸是linhaifeng 2 3 我的爷爷是就是我自己
六、闭包
1 #闭包:在一个作用域里放入定义变量,相当于打了一个包 2 def father(auth_type): 3 # print('from father %s' %name) 4 def son(): 5 # name='linhaifeng_1' 6 # print('我的爸爸是%s' %name) 7 def grandson(): 8 print('我的爷爷是%s' %auth_type) 9 grandson() 10 # print(locals()) 11 son() 12 # father('linhaifeng') 13 father('filedb')
执行结果:
1 我的爷爷是filedb
七、无参装饰器
无参装饰器=高级函数+函数嵌套
1、基本框架
1 #这就是一个实现一个装饰器最基本的架子 2 def timer(func): 3 def wrapper(): 4 func() 5 6 return wrapper
2、基本装饰器(基本框架+参数+功能+返回值+使用装饰器+语法糖@)
import time def timmer(func): #func=test def wrapper(): # print(func) start_time=time.time() func() #就是在运行test() stop_time = time.time() print('运行时间是%s' %(stop_time-start_time)) return wrapper @timmer #test=timmer(test) #在函数名前面加个@ ,这就是语法糖 def test(): time.sleep(3) print('test函数运行完毕') test()
代码说明:
1 # res=timmer(test) #返回的是wrapper的地址 2 # res() #执行的是wrapper() 3 # 4 # test=timmer(test) #返回的是wrapper的地址 5 # test() #执行的是wrapper() 6 # 7 # @timmer 就相当于 test=timmer(test)