装饰器

1、默写下面的函数

 1 import time
 2 def func():
 3     time.sleep(0.2)
 4     print("今天放假")
 5 def timme(f):  # 这里的函数名不能直接用time(),不然会报错,很可能是跟系统函数冲突
 6     def inner():
 7         Start_time = time.time()
 8         f()
 9         End_time = time.time()
10         print(End_time - Start_time)
11 
12     return inner
13 func = timme(func)
14 func()
不想修改函数的调用方式,但是还想在原来的函数前后添加功能
timmer就是一个装饰器函数,只是对一个函数有一些装饰作用
timmer就是装饰器函数,timmer()里面的f()就是被装饰函数

2、装饰器的基本原则

 原则:开放封闭原则

开放:对扩展是开放的

封闭:对修改是封闭的

3、语法糖

 把上面的装饰器用语法糖方式重新定义

 1 def timme(f):
 2     def inner():
 3         Start_time = time.time()
 4         f()
 5         End_time = time.time()
 6         print(End_time - Start_time)
 7 
 8     return inner
 9 
10 @timme                #语法糖,@装饰器函数名,这句话等价下面的func = timme(func)
11 def func():          #紧挨着的是被装饰函数
12     time.sleep(0.2)
13     print("今天放假")
14 #func = timme(func)   #用了语法糖以后,这条代码就被省去了,
15 func()

4、下面被装饰函数func加上返回值以后,当我们调用func()时候有返回值吗

 1 def timme(f):
 2     def inner():
 3         Start_time = time.time()
 4         f()
 5         End_time = time.time()
 6         print(End_time - Start_time)
 7 
 8     return inner
 9 
10 @timme                #语法糖,@装饰器函数名
11 def func():          #紧挨着的是被装饰函数
12     time.sleep(0.2)
13     print("今天放假")
14     return '过节学习'
15 ret = func()
16 print(ret)
1 0.2000114917755127
2 None
参考结果
 1 def timme(f):
 2     def inner():
 3         Start_time = time.time()
 4         ret = f()
 5         End_time = time.time()
 6         print(End_time - Start_time)
 7         return ret
 8     return inner
 9 
10 @timme                #语法糖,@装饰器函数名
11 def func():          #紧挨着的是被装饰函数
12     time.sleep(0.2)
13     print("今天放假")
14     return '过节学习'
15 ret = func()
16 print(ret)
有返回值的参考代码

5、装饰带参数函数的装饰器

 带一个参数的装饰器

 1 def timme(f):
 2     def inner(a):
 3         Start_time = time.time()
 4         ret = f(a)
 5         End_time = time.time()
 6         print(End_time - Start_time)
 7         return ret
 8     return inner
 9 
10 @timme                #语法糖,@装饰器函数名
11 def func(a):          #紧挨着的是被装饰函数
12     time.sleep(0.2)
13     print("今天放假",a)
14     return '过节学习'
15 ret = func(2)
16 print(ret)
1 今天放假 2
2 0.2000114917755127
3 过节学习
参考结果

带两个参数的装饰器

 1 def timme(f):
 2     def inner(*args):
 3         Start_time = time.time()
 4         ret = f(*args)  # 这里还需要用*把多个参数打散传入
 5         End_time = time.time()
 6         print(End_time - Start_time)
 7         return ret
 8 
 9     return inner
10 
11 @timme  # 语法糖,@装饰器函数名
12 def func2(a):  # 紧挨着的是被装饰函数
13     time.sleep(0.2)
14     print("今天放假", a)
15     return '过节学习'
16 
17 
18 @timme  # 语法糖,@装饰器函数名
19 def func3(a, b):  # 紧挨着的是被装饰函数
20     time.sleep(0.2)
21     print("今天放假", a, b)
22     return '过节学习'
23 
24 
25 ret2 = func2(2)
26 print(ret2)
27 ret3 = func3(3, 4)
28 print(ret3)
1 今天放假 2
2 0.2000114917755127
3 过节学习
4 今天放假 3 4
5 0.2000114917755127
6 过节学习
参考结果

6、包含关键字的装饰器

 1 def timme(f):
 2     def inner(*args,**kwargs):
 3         Start_time = time.time()
 4         ret = f(*args,**kwargs)  # 这里还需要用*把多个参数打散传入
 5         End_time = time.time()
 6         print(End_time - Start_time)
 7         return ret
 8 
 9     return inner
10 
11 
12 @timme  # 语法糖,@装饰器函数名
13 def func2(a,b):  # 紧挨着的是被装饰函数
14     time.sleep(0.2)
15     print("今天放假", a,b)
16     return '过节学习'
17 
18 
19 ret = func2(4,6)
20 print(ret)
21 ret2 = func2(2,b = 9)
22 print(ret2)
1 今天放假 4 6
2 0.2000114917755127
3 过节学习
4 今天放假 2 9
5 0.2000112533569336
6 过节学习
参考结果

7、装饰器的固定格式

 1 def wrapper(f):                          #装饰函数,f是被装饰函数
 2     def inner(*args,**kwargs):
 3         '''在被装饰函数之前要做的事情'''
 4         ret = f(*args,**kwargs)          #被装饰函数
 5         '''在被装饰函数之后要做的事情'''
 6         return ret
 7     return inner
 8 
 9 @wrapper                                 #语法糖,@装饰器函数名,等价于func = wrapper(func)
10 def func(a,b):                          #被装饰函数
11     time.sleep(0.5)
12     print("放假最后一天了",a,b )
13     return '假期是充实的'
14 
15 ret = func(b = 9,a = 3)                 #实际执行的是inner函数
16 print(ret)
1 放假最后一天了 3 9
2 假期是充实的
参考结果

 

 8、装饰器的聚合与打散

传参:聚合,就是说传参的时候是把几个参数一起传给函数
调用:打散,就是说具体调用的时候是一个一个参数来使用,那么好比打散来用
 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
10 def func(day):
11     print("节后第%s天"%day)
12 
13     return "继续加油干"
14 
15 ret = func(1)
16 print(ret)

上面代码结果是:

1 在被装饰之前做的事情
2 节后第1天
3 被装饰之后做的事情
4 继续加油干
参考结果

 9、带参数的装饰器

一个装饰器一般就三层,最外一层是带参数,方便用参数的设置来决定是否进行装饰,这样避免挨个挨个进行去掉装饰

 1 import time
 2 Flag = False
 3 def timmer_out(Flag):
 4     def timmer(func):
 5         def inner(*args,**kwargs):
 6             if Flag:
 7                 start_time = time.time()
 8                 ret = func(*args,**kwargs)
 9                 end_time = time.time()
10                 print(end_time - start_time)
11                 return ret
12             else:
13                 ret = func(*args, **kwargs)
14                 return  ret
15         return inner
16     return timmer
17 #timmer = timmer_out(Flag),timmer_out后面带括号就是函数调用
18 @timmer_out(Flag)
19 def get():
20     time.sleep(0.2)
21     print("快上班了")
22 
23 get()
1 快上班了
参考结果

10、装饰器进阶:多个装饰器同时装饰同一个函数

 1 def wrapper1(func):
 2     def inner1(*args,**kwargs):
 3         print("wrapper1开始装饰")
 4         ret = func(*args,**kwargs)
 5         print("wrapper1装饰结束")
 6         return ret
 7     return inner1
 8 
 9 def wrapper2(func):
10     def inner2(*args,**kwargs):
11         print("wrapper2开始装饰")
12         ret = func(*args,**kwargs)
13         print("wrapper2装饰结束")
14         return ret
15     return inner2
16 
17 def wrapper3(func):
18     def inner3(*args,**kwargs):
19         print("wrapper3开始装饰")
20         ret = func(*args,**kwargs)
21         print("wrapper3装饰结束")
22         return ret
23     return inner3
24 
25 @wrapper3
26 @wrapper2
27 @wrapper1
28 def f(a):
29     print("输入的数是:",a)
30     return "返回结束"
31 
32 print(f(666))
1 wrapper3开始装饰
2 wrapper2开始装饰
3 wrapper1开始装饰
4 输入的数是: 666
5 wrapper1装饰结束
6 wrapper2装饰结束
7 wrapper3装饰结束
8 返回结束
参考结果

多个装饰器同时装饰同一个函数的执行顺序:

 

 

 

 

 

 

 

 

 

 






posted @ 2019-04-07 16:19  xiaofeiAI  阅读(140)  评论(0编辑  收藏  举报