Python-装饰器

一、什么是装饰器:

  装饰器本身就是函数,功能是为其他函数附加功能。

二、装饰器遵循的原则:

  1、不修改被修饰函数的源代码

  2、不改变被修饰函数的调用方式

三、实现函数装饰器知识储备

  修饰器 = 高阶函数 + 函数嵌套 + 闭包

  示例:有修饰器和没有修饰器的区别:

 1 ## 常规方法实现
 2 import time
 3 
 4 def cal(l):
 5     startTime = time.time()
 6     red = 0
 7     for i in l:
 8         time.sleep(0.1)
 9         red += i
10     stopTime = time.time()
11     print("函数运行时间: %s" %(startTime-stopTime))
12     return red
13 
14 print(cal(range(100)))
15 
16 
17 -------------------------------------------------------------------------
18 ## 使用修饰器实现
19 import time
20 
21 def timer(func):
22     def wrapper(*args,**kwargs):
23         startTime = time.time()
24         red = func(*args,**kwargs)
25         stopTime = time.time()
26         print("函数运行时间:%s" %(startTime-stopTime))
27         return red
28     return wrapper
29 
30 @timer
31 def cal(l):
32     red = 0
33     for i in l:
34         time.sleep(0.1)
35         red += i
36     return red
37 
38 print(cal(range(10)))

 四、高阶函数的定义:(查看 http://www.cnblogs.com/JerryZao/p/8605019.html)

  1、函数接受的参数是一个函数名

  2、函数返回的是一个函数名

  以上满足一个即可称为高阶函数

五、函数嵌套

  1、什么是函数嵌套

    函数嵌套是在函数的内部重新定义一个新的函数,而不是调用一个函数

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('xxxx')

六、闭包

 1 '''
 2 闭包:在一个作用域里放入定义变量,相当于打了一个包
 3 '''
 4 def father(name):
 5     def son():
 6         # name='alex'
 7         print('我爸爸是 [%s]' %name)
 8         def grandson():
 9             # name='wupeiqi'
10             print('我爷爷是 [%s]' %name)
11         grandson()
12     son()
13 
14 father('xxxx')
 1 ## 再举个例子
 2 def line_conf(a, b):
 3     def line(x):
 4         return b*x + a
 5 
 6     return line
 7 
 8 line_conf(1,2)
 9 
10 # 我们可以看到,只要环境变量a,b 的值定了,那么line函数的表达式也就定了,只取决于自己的函数参数

七、无参数修饰器

  无参修饰器 = 高阶函数 + 函数嵌套

  1、基本框架

1 #这就是一个实现一个装饰器最基本的架子
2 def timer(func):
3     def wrapper():
4         func()
5 
6     return wrapper

  2、加上参数

1 def timer(func):
2     def wrapper(*args,**kwargs):
3         func(*args,**kwargs)
4     return wrapper

  3、加上功能

1 import time
2 def timer(func):
3     def wrapper(*args,**kwargs):
4         start_time=time.time()
5         func(*args,**kwargs)
6         stop_time=time.time()
7         print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
8     return wrapper

  4、加上返回值

1 import time
2 def timer(func):
3     def wrapper(*args,**kwargs):
4         start_time=time.time()
5         res=func(*args,**kwargs)
6         stop_time=time.time()
7         print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
8         return res
9     return wrapper

  5、使用装饰器

1 def cal(array):
2     res=0
3     for i in array:
4         res+=i
5     return res
6 
7 cal=timer(cal)
8 cal(range(10))

  6、语法糖 @

1 @timer  #@timer就等同于cal=timer(cal)   cal就是wrapper  ,cal()就是执行wrapper()函数
2 def cal(array):
3     res=0
4     for i in array:
5         res+=i
6     return res
7 
8 cal(range(10))

  分析示例 

 1 import time
 2 def timmer(func): #func=test1
 3     def wrapper(*args,**kwargs): #test('linhaifeng',age=18)  args=('linhaifeng')  kwargs={'age':18} 将参数完整的传给func
 4         start_time=time.time()
 5         res=func(*args,**kwargs) #就是在运行test()         func(*('linhaifeng'),**{'age':18})
 6         stop_time = time.time()
 7         print('运行时间是%s' %(stop_time-start_time))
 8         return res
 9     return wrapper
10 
11 # @timmer #test=timmer(test)
12 def test(name,age):
13     time.sleep(3)
14     print('test函数运行完毕,名字是【%s】 年龄是【%s】' %(name,age))
15     return '这是test的返回值'
16 
17 @timmer
18 def test1(name,age,gender):
19     time.sleep(1)
20     print('test1函数运行完毕,名字是【%s】 年龄是【%s】 性别【%s】' %(name,age,gender))
21     return '这是test的返回值'
22 
23 # res=test('linhaifeng',age=18)  #就是在运行wrapper
24 # # print(res)
25 # test1('alex',18,'male')
26 
27 test1('alex',18,'male')

八、装饰器应用案例:

  写一个模拟JD网站,用户认证登录网站和购物加入购物车功能程序

  实现功能:用装饰器给所有的函数加上验证功能

  示例1、

 1 user_list=[
 2     {'name':'alex','passwd':'123'},
 3     {'name':'linhaifeng','passwd':'123'},
 4     {'name':'wupeiqi','passwd':'123'},
 5     {'name':'yuanhao','passwd':'123'},
 6 ]
 7 current_dic={'username':None,'login':False}
 8 
 9 def auth(auth_type='filedb'):
10     def auth_func(func):
11         def wrapper(*args,**kwargs):
12             print('认证类型是',auth_type)
13             if auth_type == 'filedb':
14                 if current_dic['username'] and current_dic['login']:
15                     res = func(*args, **kwargs)
16                     return res
17                 username=input('用户名:').strip()
18                 passwd=input('密码:').strip()
19                 for user_dic in user_list:
20                     if username == user_dic['name'] and passwd == user_dic['passwd']:
21                         current_dic['username']=username
22                         current_dic['login']=True
23                         res = func(*args, **kwargs)
24                         return res
25                 else:
26                     print('用户名或者密码错误')
27             elif auth_type == 'ldap':
28                 print('鬼才特么会玩')
29                 res = func(*args, **kwargs)
30                 return res
31             else:
32                 print('鬼才知道你用的什么认证方式')
33                 res = func(*args, **kwargs)
34                 return res
35 
36         return wrapper
37     return auth_func
38 
39 @auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type  --->index=auth_func(index)
40 def index():
41     print('欢迎来到京东主页')
42 
43 @auth(auth_type='ldap')
44 def home(name):
45     print('欢迎回家%s' %name)
46 #
47 @auth(auth_type='sssssss')
48 def shopping_car(name):
49     print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))
50 
51 # print('before-->',current_dic)
52 # index()
53 # print('after--->',current_dic)
54 # home('产品经理')
55 shopping_car('产品经理')
没有判断验证方式,直接就显示购物车结果。
 1 user_list=[
 2     {'name':'alex','passwd':'123'},
 3     {'name':'linhaifeng','passwd':'123'},
 4     {'name':'wupeiqi','passwd':'123'},
 5     {'name':'yuanhao','passwd':'123'},
 6 ]
 7 
 8 current_user={'username':None,'login':False}
 9 
10 def auth_deco(func):
11     def wrapper(*args,**kwargs):
12         if current_user['username'] and current_user['login']:
13             res=func(*args,**kwargs)
14             return res
15         username=input('用户名: ').strip()
16         passwd=input('密码: ').strip()
17 
18         for index,user_dic in enumerate(user_list):
19             if username == user_dic['name'] and passwd == user_dic['passwd']:
20                 current_user['username']=username
21 
22                 current_user['login']=True
23                 res=func(*args,**kwargs)
24                 return res
25                 break
26         else:
27             print('用户名或者密码错误,重新登录')
28 
29     return wrapper
30 
31 @auth_deco
32 def index():
33     print('欢迎来到主页面')
34 
35 @auth_deco
36 def home():
37     print('这里是你家')
38 
39 def shopping_car():
40     print('查看购物车啊亲')
41 
42 def order():
43     print('查看订单啊亲')
44 
45 print(user_list)
46 # index()
47 print(user_list)
48 home()
49 
50 无参装饰器
无参数(语法糖)
 1 user_list=[
 2     {'name':'alex','passwd':'123'},
 3     {'name':'linhaifeng','passwd':'123'},
 4     {'name':'wupeiqi','passwd':'123'},
 5     {'name':'yuanhao','passwd':'123'},
 6 ]
 7 
 8 current_user={'username':None,'login':False}
 9 def auth(auth_type='file'):
10     def auth_deco(func):
11         def wrapper(*args,**kwargs):
12             if auth_type == 'file':
13                 if current_user['username'] and current_user['login']:
14                     res=func(*args,**kwargs)
15                     return res
16                 username=input('用户名: ').strip()
17                 passwd=input('密码: ').strip()
18 
19                 for index,user_dic in enumerate(user_list):
20                     if username == user_dic['name'] and passwd == user_dic['passwd']:
21                         current_user['username']=username
22                         current_user['login']=True
23                         res=func(*args,**kwargs)
24                         return res
25                         break
26                 else:
27                     print('用户名或者密码错误,重新登录')
28             elif auth_type == 'ldap':
29                 print('巴拉巴拉小魔仙')
30                 res=func(*args,**kwargs)
31                 return res
32         return wrapper
33     return auth_deco
34 
35 
36 #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
37 #就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
38 @auth(auth_type='ldap')
39 def index():
40     print('欢迎来到主页面')
41 
42 @auth(auth_type='ldap')
43 def home():
44     print('这里是你家')
45 
46 def shopping_car():
47     print('查看购物车啊亲')
48 
49 def order():
50     print('查看订单啊亲')
51 
52 # print(user_list)
53 index()
54 # print(user_list)
55 home()
56 
57 带参装饰器
含有参数

九、补充:

  解压序列

 1 a,b,c = [1,2,3]
 2 
 3 --->
 4 
 5 a=1
 6 b=2
 7 c=3
 8 
 9 
10 s = [1,2,3,5,6,7,8,8,9,0,0,32,453,5435,23,5,675,6]
11 a,*_,b = s
12 print(a) # 1
13 print(b) # 6

  值交换

1 a = 1
2 b = 2
3 
4 ----->
5 
6 a,b = b,a
7 
8 # 这样就ab的值交换了

  

为什么要坚持,想一想当初!
原文地址:https://www.cnblogs.com/JerryZao/p/8645266.html