Python装饰器
定义
本质就是函数,功能 为其它函数添加附加功能
原则:
- 不修改被修饰函数的源代码
- 不修改被修饰函数的调用方式
装饰器的知识储备
装饰器 = 高阶函数+函数嵌套+闭包
这里面要明确高阶函数的定义
1 import time#导入时间模块儿 2 def foo(func): # func = test 3 def bar(*args,**kwargs): 4 start_time = time.time() 5 res=func(*args,**kwargs) # 这里就是在运行test() 赋予变量 6 stop_time = time.time() 7 print("狼来了的时间为%s" %(stop_time-start_time)) 8 return res # 返回test()的值 9 return bar 10 @foo # @foo 相当于 test=foo(test) 调用foo函数并将test传给func 11 def test(name,age): 12 time.sleep(1) 13 print("名字叫%s年龄为%s的狼来了" %(name,age)) 14 return "村里的羊被吃了" 15 ret = test("灰太狼",age=10) # test()意在运行bar() # 输出res的返回值 16 print(ret)
分布式讲解:
高阶函数的定义
1、函数接收的参数是一个函数名 2、函数的返回值是一个函数名
以上条件任意满足一条,都可以称之为高阶函数
1 def foo(): 2 print('我的函数名字作为参数传给高阶函数啦') 3 def gao_jie1(func): # 传函数名 func = foo 4 print('我就是高阶函数1号,我接收的参数名是%s' %func) 5 func() # 意在运行 foo()函数 6 7 def gao_jie2(func): # func = foo 8 print('我就是高阶函数2号,我的返回值是%s' %func) 9 return func # 此时func为返回foo的的内存地址 10 11 gao_jie1(foo) 12 print(gao_jie2(foo)) 13 14 输出 15 我就是高阶函数1号,我接收的参数名是<function foo at 0x000001FDF179F598> 16 我的函数名字作为参数传给高阶函数啦 17 我就是高阶函数2号,我的返回值是<function foo at 0x000001FDF179F598> 18 <function foo at 0x000001FDF179F598>
1 import time 2 def foo(): 3 time.sleep(2) 4 print("狼来了") 5 def test(func): # func = foo 6 start_time = time.time() 7 func() # func()意在调用 foo()函数 8 stop_time = time.time() 9 print("狼来的时间为%s" %(stop_time-start_time)) 10 test(foo) # 调用test()函数 并用函数名为参数传进去
总结:1、函数接收的参数是一个函数名
作用:在不修改函数源代码的前提下添加新功能
不足:改变了函数的调用方式
#高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名 import time def foo(): time.sleep(2) print("狼来了") def test(func): # func = foo的内存地址 start_time = time.time() return func # 返回值为foo的内存地址 stop_time = time.time() print("狼来的时间为%s" %(stop_time-start_time)) foo = test(foo) # 调用test函数并将函数名foo做为参数传进去 print(foo) # 输出返回值的结果 foo的内存地址 foo() # 运行foo()函数 #没有改变函数foo的调用方式,但是也没有给函数增加新功能
总结:2、函数的返回值是一个函数名
作用:不修改函数的调用方式
不足:没有为函数增加新的功能
函数嵌套
1 def father(name): 2 print('from father %s' %name) 3 def son(): 4 print('from son') 5 def grandson(): 6 print('from grandson') 7 grandson() 8 son() 9 father('舒克') 10 11 输出 12 from father 舒克 13 from son 14 from grandson
闭包
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 father('舒克')
无参装饰器=高阶函数+嵌套函数
基本框架
1
2
3
4
5
|
# 无参装饰器,这是一个实现装饰器最基本的框架 def timmer(func): def bar(): func() return bar |
加入参数之后
1
2
3
4
5
|
# 带参数装饰器 def timmer(func): def bar( * args, * * kwargs): func( * args, * * kwargs) return bar |
加入时间功能
1
2
3
4
5
6
7
8
9
|
# 加一个时间的小功能 import time def timmer(func): def bar( * args, * * kwargs): start_time = time.time() func( * args, * * kwargs) stop_time = time.time() print ( "狼来的时间为%s" % (stop_time - start_time)) return bar |
加入函数运行的返回值
1
2
3
4
5
6
7
8
9
10
|
# 加入函数返回值 import time def timmer(func): def bar( * args, * * kwargs): start_time = time.time() res = func( * args, * * kwargs) stop_time = time.time() print ( "狼来的时间为%s" % (stop_time - start_time)) return res return bar |
使用装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import time def timmer(func): def bar( * args, * * kwargs): start_time = time.time() res = func( * args, * * kwargs) stop_time = time.time() print ( "博尔特跑10米的时间为%s" % (stop_time - start_time)) return res return bar # 使用装饰器 def test(): time.sleep( 1 ) print ( "到达终点" ) return "世界飞人" test = timmer(test) print (test()) 输出 到达终点 博尔特跑 10 米的时间为 1.0006155967712402 世界飞人 |
语法糖@
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import time def timmer(func): def bar( * args, * * kwargs): start_time = time.time() res = func( * args, * * kwargs) stop_time = time.time() print ( "博尔特跑10米的时间为%s" % (stop_time - start_time)) return res return bar # 使用装饰器 @timmer # @timmer就相当于 test=timmer(test) def test(): time.sleep( 1 ) print ( "到达终点" ) return "世界飞人" # test=timmer(test) print (test()) # test()是在运行bar()函数 |
应用示例
user_list=[ {'name':'alex','passwd':'123'}, {'name':'linhaifeng','passwd':'123'}, {'name':'wupeiqi','passwd':'123'}, {'name':'yuanhao','passwd':'123'}, {'name':'病毒尖er','passwd':'123'}, ] current_user={'username':None,'login':False} def auth_func(func): # 用户登陆验证 def bar(*args,**kwargs): if current_user["username"] and current_user["login"]: res = func(*args,**kwargs) return res for i in range(3): username = input("请输入用户名:").strip() passwd = input("请输入密码:").strip() for item in user_list: if username == item["name"] and passwd == item["passwd"]: current_user["username"] = username current_user["login"] = True res=func(*args,**kwargs) return res else: print("您输入的用户名或者密码有误") return bar @auth_func # 相当于index=auth_func(index) def index(): print("欢迎来到京东商城" ) @auth_func # 相当于home=auth_func(home) def home(name): print("%s欢迎回家" %name) @auth_func # 相当于shop_car=auth_func() def shop_car(name): print("%s的购物车是空的,赶紧购物咯" %name) index() home(current_user["username"]) shop_car(current_user["username"])
1 user_list=[ 2 {'name':'alex','passwd':'123'}, 3 {'name':'linhaifeng','passwd':'123'}, 4 {'name':'wupeiqi','passwd':'123'}, 5 {'name':'yuanhao','passwd':'123'}, 6 {'name':'病毒尖er','passwd':'123'}, 7 ] 8 current_user={'username':None,'login':False} 9 def auth(auth_type="file"): 10 def auth_func(func): # 用户登陆验证 11 def bar(*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 for i in range(3): # 给用户三次重复输入的机会 防止进入其它功能进入下一层 17 username = input("请输入用户名:").strip() 18 passwd = input("请输入密码:").strip() 19 for item in user_list: 20 if username == item["name"] and passwd == item["passwd"]: 21 current_user["username"] = username 22 current_user["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 return bar 32 return auth_func 33 @auth(auth_type="file") 34 def index(): 35 print("欢迎来到京东商城" ) 36 @auth(auth_type="ldap") # 传参数 类型对应 37 def home(name): 38 print("%s欢迎回家" %name) 39 @auth(auth_type="file") 40 def shop_car(name): 41 print("%s的购物车是空的,赶紧购物咯" %name) 42 43 index() 44 home(current_user["username"]) 45 shop_car(current_user["username"])