python开发函数进阶:装饰器

一,装饰器本质

闭包函数

功能:就是在不改变原函数调用方式的情况下,在这个函数前后加上扩展功能

作用:解耦,尽量的让代码分离,小功能之前的分离。

   解耦目的,提高代码的重用性

二,设计模式

开放封闭原则

*对扩展是开放的

*对修改是封闭的

三,代码解释

*通用代码

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 
 4 def timmer(func):  #---> jjj
 5     def inner(*args,**kwargs):
 6         ret = func(*args,**kwargs)  # --->ret = jjj()
 7         # print('没有返回值的调用')
 8         return ret
 9     return inner
10 
11 @timmer #jjj = timmer(jjj)  语法糖
12 def jjj():
13     return 123
14 # jjj()    #调用函数,如果被装饰的函数有返回值,就需要下边的代码
15 ret = jjj()  #==>inner    有返回值
16 print(ret)  #返回123

执行顺序

 

*用装饰器简单实现用户登录,登陆一个函数成功,无需再次登陆

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 
 4 tag = False
 5 
 6 def login(func):
 7     def inner(*args,**kwargs):
 8         global tag
 9         if tag == False:
10             user = input('please your username>>>:')
11             pwd = input('please your password>>>:')
12             f = open('aaa','r',encoding='utf-8')
13             for i in f:
14                 user_pwd = eval(i)
15                 if user == user_pwd['name'] and pwd == user_pwd['password']:
16                     tag = True
17             f.close()
18         if tag:
19             ret = func(*args,**kwargs)
20             return ret
21     return inner
22 
23 @login
24 def haha(*args,**kwargs):
25     print('中国动漫')
26     pass
27 
28 @login
29 def hengheng(*args,**kwargs):
30     print('美国动漫')
31     pass
32 ##########用户调用方式
33 haha()
34 hengheng()

 *统计函数中有多少个函数被装饰了

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 
 4 l = []
 5 def wrapper(func):
 6     #l.append(func)  #统计当前程序中有多少个函数被装饰了
 7     def inner(*args,**kwargs):
 8         l.append(func)  #统计本次程序执行有多少个带这个装饰器的函数被调用了
 9         ret = func(*args,**kwargs)
10         return ret
11     return inner
12 
13 @wrapper  #f1 = wrapper(f1)
14 def f1():
15     print('in f1')
16 
17 @wrapper #f2 = wrapper(f2)
18 def f2():
19     print('in f2')
20 
21 @wrapper #f2 = wrapper(f2)
22 def f3():
23     print('in f3')
24 f1()
25 f2()
26 f3()
27 
28 print(len(l))

四,双层带参数的装饰器

顾名思义,就是给装饰器添加参数

可以控制被装饰的函数是否需要这个装饰器,或者其他用法

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 
 4 #带参数的装饰器 开关 ,控制是否需要装饰器
 5 
 6 F = False    #通过这里控制是否需要装饰器
 7 def outer(flag):
 8     #以下是装饰器
 9     def wrapper(func):
10         def inner(*args,**kwargs):
11             if flag:
12                 print('before') #被装饰代码运行之前
13                 ret = func(*args,**kwargs)  #被装饰的代码
14                 print('after')   #被装饰代码运行之后
15             else:
16                 ret = func(*args, **kwargs)
17             return ret
18         return inner
19     ###########################
20     return wrapper
21 
22 @outer(F)   # F默认是FALSE,那么装饰器没有用上,因为 if false: ret = func(),因为加了括号直接执行,返回了wrapper,后面就是装饰器过程了
23 def hahaha():
24     print('hahaha')
25 
26 @outer(F)   # F如果是TRUE,就用上了装饰器
27 def shuangww():
28     print('shuangwaiwai')
29 
30 shuangww()
31 hahaha()

执行过程

 

五,多个装饰器装饰一个函数(非重点)

 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 
 4 #多个装饰器装饰一个函数
 5 def qqxing(func):  #func = pipixia_inner
 6     def qqxing_inner(*args,**kwargs):
 7         print('in qqxing:before')
 8         ret = func(*args,**kwargs)  #pipixia_inner
 9         print('in qqxing:after')
10         return ret
11     return qqxing_inner
12 
13 def pipixia(func):  #dapangxie
14     def pipixia_inner(*args,**kwargs):
15         print('in pipixia:before')
16         ret = func(*args,**kwargs)      #dapangxie
17         print('in pipixia:after')
18         return ret
19     return pipixia_inner
20 
21 #qqxing(pipixia_inner)  -->dapangxie = qqxing_inner()
22 @qqxing    #dapangxie = qqxing(dapangxie)  -->dapangxie = qqxing(pipixia(dapangxie)) -->
23 @pipixia   #dapangxie = pipixia(dapangxie)
24 def dapangxie():
25     print("饿了么")
26 dapangxie()
27 
28 #dapangxie = pipixia(dapangxie)
29 #dapangxie = qqxing(dapangxie)  -->dapangxie = qqxing(pipixia(dapangxie))
30                                             #pipixia(dapangxie) == >pipixia_inner
31                                             #qqxing(pipixia_inner) = qqxing_inner
32 #dapangxie()  ==> qqxing_inner()
原文地址:https://www.cnblogs.com/jokerbj/p/7247901.html