装饰器
time模块
1 import time 2 time.time()#1970年到此时此刻的秒数,可以用来计算程序运行的时间 3 time.sleep(5)#表示程序执行到这里的时候停一会 4 print('ahj')
场景:计算一个代码的执行时间:
1 import time 2 def func(): 3 start=time.time()#给出程序开始运行的初始时间 4 print('老板好,领导好') 5 end=time.time()#给出程序运行结束的时间 6 print(end-start)#计算程序开始运行到结束运行的时间差 7 func()
需求:通过使用time模块确实是可以计算代码执行的时间。使用上面的代码在代码量少的地方可以很容易实现,但是如果代码量很大的话,再不断重复敲代码就不合适了。那么这个重复的功能就可以通过函数来实现,到时候在不同的代码里面加上这个函数就可以实现功能即可。
1 import time 2 def timer(f):#计算程序执行时间的函数 3 start = time.time() # 给出程序开始运行的初始时间 4 f()#这里接收到func函数然后开始运行 5 end = time.time() # 给出程序运行结束的时间 6 print(end - start) # 计算程序开始运行到结束运行的时间差 7 def func(): 8 time.sleep(0.1) 9 print('老板好,领导好') 10 timer(func)#在这里将func函数传递给第3行代码 11 #注意这段代码的精妙之处:执行顺序1>7>2>9>3>4>8>9>5>6 12 13 D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/14.py 14 老板好,领导好 15 0.10072994232177734 16 17 Process finished with exit code 0
这段代码还是优点复杂,可以再改进一下
1 import time 2 def func(): 3 time.sleep(0.1) 4 print('老板好,领导好') 5 6 def timer(): 7 start = time.time() # 给出程序开始运行的初始时间 8 func()#这里接收到func函数然后开始运行 9 end = time.time() # 给出程序运行结束的时间 10 print(end - start) # 计算程序开始运行到结束运行的时间差 11 12 timer()#在这里将func函数传递给第3行代码 13 #注意这段代码的精妙之处:执行顺序1>2>6>12>7>8>3>4>9>10
继续改进
1 import time 2 def func(): 3 time.sleep(0.1) 4 print('老板好,领导好') 5 6 def timer(func): 7 start = time.time() # 给出程序开始运行的初始时间 8 func()#这里接收到func函数然后开始运行 9 end = time.time() # 给出程序运行结束的时间 10 print(end - start) # 计算程序开始运行到结束运行的时间差 11 12 timer(func)#在这里将直接加上func函数,这样以后遇到其他函数的时候,就能够用其他函数名直接将func替换掉即可 13 #注意这段代码的精妙之处:执行顺序1>2>6>12>7>8>3>4>9>10
但是还是不够简单:再继续修改
1 import time 2 def func(): 3 time.sleep(0.1) 4 print('老板好,领导好') 5 6 #够建一个闭包,定义一个装饰函数 7 def timer(func): 8 def inner(): 9 start = time.time() # 给出程序开始运行的初始时间 10 func()#这里接收到func函数然后开始运行,func就是被装饰的函数 11 end = time.time() # 给出程序运行结束的时间 12 print(end - start) # 计算程序开始运行到结束运行的时间差 13 return inner# 14 15 func=timer(func) 16 func()#这样处理以后只要我在实际写代码的过程中,执行func那么就能够执行timer和func都能实现执行 17 #注意这段代码的精妙之处:执行顺序1>2>7>15>8>13>15>10>9>10>3>4>11>12
装饰器的作用:不想修改函数的调用方式,但是还想再原来的函数前后添加功能。
在上面的例子中:timmer就是一个装饰器函数,只是对一个函数有些装饰作用。
上面程序的执行顺序如下
再对上面的代码进行修改提升
将计算时间的功能,单独提出来
import time def timer(func):#定义一个装饰器函数 def inner(): start = time.time() func()#被装饰的函数 end = time.time() print(end - start) return inner # @timer用@加上上面闭包函数的函数名形成的这么一句话叫做语法糖,这句话的作用就是替代了# func=timer(func),这段代码,这才是实际上装饰器应该有的样子 def func(): time.sleep(0.1) print('老板好,领导好') func=timer(func) func()
进一步修改
import time def timer(func):#定义一个装饰器函数 def inner(): start = time.time() func()#被装饰的函数 end = time.time() print(end - start) return inner @timer#用@加上上面闭包函数的函数名形成的这么一句话叫做语法糖,这句话的作用就是替代了# func=timer(func),这段代码,这才是实际上装饰器应该有的样子 def func(): time.sleep(0.1) print('老板好,领导好') # func=timer(func) func()
延申
def outer(): def inner(): return 'inner' inner() outer() #注意这段代码的执行顺序:1>5>5>4>3>4,因为在第五行只是执行了outer函数,inner函数的返回值没有被接收,所以结果位none D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/练习.py Process finished with exit code 0
1 import time 2 3 def timer(func):#定义一个装饰器函数 4 def inner(): 5 start = time.time() 6 func()#被装饰的函数 7 end = time.time() 8 tmsj=end - start 9 print('代码的运行时间是:',tmsj)#注意这里一定要加上这个逗号 10 return func() 11 return inner 12 13 @timer 14 def func(): 15 time.sleep(0.1) 16 print('老板好,领导好') 17 return '新年好' 18 19 20 # func=timer(func) 21 print(func()) 22 # ret=func() 23 #print(ret) 24 25 D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/456.py 26 老板好,领导好 27 代码的运行时间是: 0.10079765319824219 28 老板好,领导好 29 新年好 30 31 Process finished with exit code 0
对比代码的运行结果
1 import time 2 3 def timer(func):#定义一个装饰器函数 4 def inner(): 5 start = time.time() 6 ret=func()#被装饰的函数 7 end = time.time() 8 tmsj=end - start 9 print('代码的运行时间是:',tmsj)#注意这里一定要加上这个逗号 10 return ret 11 return inner 12 13 @timer 14 def func(): 15 time.sleep(0.1) 16 print('老板好,领导好') 17 return '新年好' 18 19 20 # func=timer(func) 21 print(func()) 22 # ret=func() 23 #print(ret) 24 25 D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/456.py 26 老板好,领导好 27 代码的运行时间是: 0.10103273391723633 28 新年好 29 30 Process finished with exit code 0
装饰器带参数的装饰器
1 import time 2 3 def timer(func):#定义一个装饰器函数 4 def inner(a): 5 start = time.time() 6 ret=func(a)#被装饰的函数 7 end = time.time() 8 tmsj=end - start 9 print('代码的运行时间是:',tmsj)#注意这里一定要加上这个逗号 10 return ret 11 return inner 12 13 @timer 14 def func(a): 15 time.sleep(0.1) 16 print('老板好,领导好',a)#增加了变量参数a 17 return '新年好' 18 19 20 # func=timer(func) 21 print(func(1)) 22 # ret=func() 23 #print(ret) 24 25 26 D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/456.py 27 老板好,领导好 1 28 代码的运行时间是: 0.10066628456115723 29 新年好 30 31 Process finished with exit code 0
带多个参数的装饰器
1 import time 2 3 def timer(f):#定义一个装饰器函数 4 def inner(*args,**kwargs): 5 start = time.time() 6 ret=f(*args,**kwargs)#被装饰的函数,注意这里的函数f和前面timmer中的参数要保持一致 7 end = time.time() 8 tmsj=end - start 9 print('代码的运行时间是:',tmsj)#注意这里一定要加上这个逗号 10 return ret 11 return inner 12 13 @timer 14 def func(a,b): 15 time.sleep(0.1) 16 print('老板好,领导好',a,b)#增加了变量a 17 return '新年好' 18 19 @timer 20 def func2(a):#增加为两个参数 21 time.sleep(0.1) 22 print('老板好,领导好',a)#增加了变量a 23 return '新年好' 24 25 # func=timer(func) 26 27 print(func(1,b=2)) 28 print(func2(1)) 29 30 31 D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/456.py 32 老板好,领导好 1 2 33 代码的运行时间是: 0.10066032409667969 34 新年好 35 老板好,领导好 1 36 代码的运行时间是: 0.10030198097229004 37 新年好 38 39 Process finished with exit code 0
装饰器的通用模板
1 #装饰器的通用模板 2 3 def timer(f):#定义一个装饰器函数,f是被装饰的函数 4 def inner(*args,**kwargs): 5 #这里加上的是被装饰函数之前要做的事 6 ret=f(*args,**kwargs) 7 # 这里加上的是被装饰函数之后要做的事 8 return ret 9 return inner 10 11 @timer #等价于func=timer(func) 12 def func(a,b): 13 time.sleep(0.1) 14 print('老板好,领导好',a,b)#增加了变量a 15 return '新年好' 16 17 ret=func()#注意这里的这个func代表的是innner,实际上装饰器讲的就是一个完整的闭包
代码开放封闭原则:
开放:对扩展是开放的,对于功能的扩展是开放的。
封闭:对修改是封闭的,但是不能修改原来的代码,因为未来遇到的代码可能数量会非常大,如果自己私自修改其中的某些代码,那么就会引起很多不必要的麻烦。所以不到万不得已不能修改别人以前写的代码。修改别人的代码,在专业上叫做代码重构。
装饰器的进阶
装饰器的复习
def wrapper(func):
def inner(*args,**kwargs):
print('引用前要做的事')
ret=func(*args,**kwargs)
print('引用后要做的事')
return ret
return inner
@wrapper#实际上就等价于holiday=wrapper(holiday)
def holiday(day):
print('放假%s天'%day)
return '很开心'
ret=holiday(3)#注意ret这里所承接的内容是第12行代码的返回值
print(ret)
装饰器的执行过程:装饰
上面那段代码的执行顺序
对上段代码自己的理解
1 #先构造一个装饰器的闭包
2
3 def wrapper():
4 def inner(*args,**kwargs):
5 print('前')
6 # ret=func(*args,**kwargs)
7 print('后')
8 # return ret
9 return inner
10
11 wrapper()()
12
13 D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/14.py
14 前
15 后
16
17 Process finished with exit code 0
进一步改进
1 def wrapper(func):
2 def inner(*args,**kwargs):
3 print('前')
4 ret=func(*args,**kwargs)
5 print('后')
6 return ret
7 return inner
8
9 @wrapper #func=wrapper(func)
10 def holiday(day):
11 print('放假%s天'%day)
12 return '很开心'
13
14 inn=holiday(3)#注意等号右边的holiday(3)就相当于inner(3)
15 print(inn)
16
17
18 D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/14.py
19 前
20 放假3天
21 后
22 很开心
23
24 Process finished with exit code 0
第22行的很开心是第6行和第12行代码的综合结果,第12行返回‘很开心“,然后第6行的return再把’很开心‘这行代码返回给第14行的inn,第15行执行出结果,所以第6行和第12行代码缺一不可,否则就会报none
延申
def outer(*args):
print(args)
#print(*args)
outer(1,2,3,4)
outer(*[1,2,3,4])
outer(*(1,2,3,4))
#三个结果完全相同
延申进阶
def outer(*args):
print(args)
print(*args)
def inner(*args):
print('inner:',args)
inner(*args)
outer(1,2,3,4)
#三个结果完全相同
D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/456.py
(1, 2, 3, 4)
1 2 3 4
inner: (1, 2, 3, 4)
Process finished with exit code 0
新的知识点
def wahaha():
'''
一个打印哇哈哈的函数
:return:
'''
print('哇哈哈')
print(wahaha.__name__)#打印出函数的字符串名称
print(wahaha.__doc__)#打印出函数的注释
同理将这个新的知识点应用到上面的代码中
1 def wrapper(func):
2 def inner(*args,**kwargs):
3 print('前')
4 ret=func(*args,**kwargs)
5 print('后')
6 return ret
7 return inner
8
9 @wrapper #func=wrapper(func)
10 def holiday(day):
11 print('放假%s天'%day)
12 return '很开心'
13
14 print(holiday.__name__)
15
16
17 D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/14.py
18 inner
19
20 Process finished with exit code 0
由于holiday在代码中实际上指代的是inner,所以打印出来的结果就是inner
再进阶
1 from functools import wraps
2 def wrapper(func):
3 @wraps(func)#加上一个内置的装饰器,但是注意这里的装饰器里面含有参数
4 def inner(*args,**kwargs):
5 print('前')
6 ret=func(*args,**kwargs)
7 print('后')
8 return ret
9 return inner
10
11 @wrapper #func=wrapper(func)
12 def holiday(day):
13 '''这是一个放假的通知'''
14 print('放假%s天'%day)
15 return '很开心'
16
17 print(holiday.__name__)#加上内置的装饰器以后,打印出来的结果就是holiday本身了
18 print(holiday.__doc__)
19
20 inn=holiday(3)#注意等号右边的holiday(3)就相当于inner(3)
21 print(inn)
22
23
24 D:\anoconda\python.exe F:/python/python学习/人工智能/第一阶段day2/14.py
25 holiday
26 这是一个放假的通知
27 前
28 放假3天
29 后
30 很开心
31
32 Process finished with exit code 0
通过调用python内置的装饰器,打印出了holiday