一、装饰器定义
器即函数;装饰即修饰,意指为其他函数添加新功能;
装饰器定义:本质就是函数,功能是为其他函数添加新功能
二、装饰器的原则
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')