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的值交换了
为什么要坚持,想一想当初!