Python基础-----装饰器
一、装饰器定义
器即函数;装饰即修饰,意指为其他函数添加新功能;
装饰器定义:本质就是函数,功能是为其他函数添加新功能
二、装饰器的原则
1.不修改被装饰函数的源代码(开放封闭原则)
2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式
三、高阶函数
满足如下条件之一就可称之为高阶函数
1.函数接收的参数是一个函数名
2.函数的返回值是一个函数名
高阶函数总结
1.函数接收的参数是一个函数名
作用:在不修改函数源代码的前提下,为函数添加新功能,
不足:会改变函数的调用方式
2.函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:不能添加新功能
四、闭包
闭包:在一个作用域里放入定义变量(或嵌套函数),相当于打了一个包
想要给内部传入参数,用闭包的话只需要在最外部传入即可
1 def father(name): 2 def son(): 3 def grandson(): 4 print('from %s'%name) 5 grandson() 6 son() 7 8 father('Meanwey')
五、装饰器框架实现
1 import time 2 def timmer(func): #func = test 3 def wrapper(): 4 start_time = time.time() 5 func() #执行test函数 6 stop_time = time.time() 7 print('运行时间%s'%(stop_time - start_time)) 8 return wrapper 9 10 def test(): 11 time.sleep(3) 12 print('函数运行完毕') 13 14 test = timmer(test) #返回的是wrapper的函数地址 15 test() #执行wrapper函数,内部再运行test函数
上面代码符合装饰器的基本原则,但是调用test函数之前进行了赋值操作
六、装饰器语法糖
@装饰函数 (将该句代码放置于修饰函数前即可)
就上例来讲,@timmer 就相当于 test = timmer(test)
1 import time 2 def timmer(func): #func = test 3 def wrapper(): 4 start_time = time.time() 5 func() #执行test函数 6 stop_time = time.time() 7 print('运行时间%s'%(stop_time - start_time)) 8 return wrapper 9 10 @timmer #等同于test = timmer(test) 11 def test(): 12 time.sleep(3) 13 print('函数运行完毕') 14 15 test()
七、加上返回值
1 import time 2 def timmer(func): #func = test 3 def wrapper(): 4 start_time = time.time() 5 res = func() #执行test函数 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(): 13 time.sleep(3) 14 print('函数运行完毕') 15 return '这是test的返回值' 16 a = test() #实际执行wrapper函数 17 print(a)
八、加上参数
1 import time 2 def timmer(func): #func = test 3 def wrapper(name,age): 4 start_time = time.time() 5 res = func(name,age) #执行test函数,参数来自wrapper接收的参数 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('我叫%s,年龄%d'%(name,age)) 15 return '这是test的返回值' 16 a = test('alex',18) #实际执行wrapper函数
但是参数是固定的,不适用于所有函数,则改变如下:
1 import time 2 def timmer(func): #func = test 3 def wrapper(*args,**kwargs): #可以用* **来传入多参数 4 start_time = time.time() 5 res = func(*args,**kwargs) #执行test函数,参数来自wrapper接收的参数 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('我叫%s,年龄%d'%(name,age)) 15 return '这是test的返回值' 16 17 @timmer 18 def test1(name,age,gender): 19 time.sleep(3) 20 print('我叫%s,年龄%d,性别%s'%(name,age,gender)) 21 return '这是test的返回值' 22 a = test('alex',18) #实际执行wrapper函数 23 b = test1('tony',22,'male') #该处将'tony',22,'male'参数放入*args == *('tony',22,'male')(一一对应,相当于解压)
九、列表解压
如要获取列表的第一个和最后一个值,不用索引来取
1 l = [10,2,3,4,5,7,5,4,2,32] 2 first_num,*other_num,last_num = l # *+变量名 表示中间的所有元素 3 print(first_num,last_num) 4 print(*other_num)
如需互换两个变量的值
1 a = 1 2 b = 2 3 a,b = b,a 4 print(a,b)
十、实例(验证功能装饰器)
1 user_list = [ 2 {'name':'a','password':'123'}, 3 {'name':'b','password':'123'}, 4 {'name':'c','password':'123'}, 5 {'name':'d','password':'123'} 6 ] #所有用户信息列表(值为字符串类型) 7 8 current_user = {'username':None,'login':False} #记录用户当前登录状态 9 10 def auth_func(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() #上面if不成立,则登录 16 password = input('密码:').strip() 17 for user_dic in user_list: #for遍历的是用户列表的中用户信息字典 18 if username == user_dic['name'] and password == user_dic['password']: #登录验证 19 current_user['username'] = username #登录成功,更改用户状态 20 current_user['login'] = True 21 res = func(*args,**kwargs) 22 return res 23 else: #该处else没放在if下是因为,要遍历所有的用户列表才能判断是否真的有错 24 print('用户名或密码错误,请重新登录!') 25 return wrapper 26 27 @auth_func 28 def home(name): 29 print('欢迎 %s 来到主页'%name) 30 31 @auth_func 32 def shopping_car(name): 33 print('%s 的购物车里有:学习用品,生活用品!'%name) 34 35 home('Jerry') 36 print(current_user) 37 shopping_car('Jerry')