Py修行路 python基础 (十)装饰器
装饰器
一、定义
装饰器:顾名思义,就是对某个东西起到装饰修饰的功能。
python中的装饰器,其本质上就是一个python函数,它可以让其他函数在不需要任何代码变动的前提下增加额外功能。通俗理解就是 函数 闭包 的实用。
二、语法及注意事项
1、书写规范 @ *** ***指装饰器的函数名
2、装饰器作为一个函数,他会把其下一行的主函数名作为变量,传递到自己的函数去调用。再重新赋值主函数。
3、装饰器必须放到被装饰的函数上边,并且独占一行;多个装饰器下 ,按照先下后上执行。
三、为什么要用装饰器?
开放封闭原则
源代码上线之后,主函数的定义和调用方式尽量避免更改。装饰器本身在源代码中就是可调用的对象。
四、装饰器使用举例
原函数如下:
1 import time 2 def index(): 3 time.sleep(3) 4 print("welcome to oldboy") 5 index()
执行结果:
welcome to oldboy
在原函数不被更改的情况下,增加新的功能:计算主函数执行的时间!
1、最原始的无参装饰器(无位置参数)。
1 import time 2 3 def timer(func): 4 def wrapper(): 5 start_time=time.time() 6 func() 7 stop_time = time.time() 8 print("running time:%s"%(stop_time-start_time)) 9 return wrapper 10 @timer 11 def index(): 12 time.sleep(3) 13 print("welcome to oldboy") 14 index()
执行结果:
1 welcome to oldboy 2 running time:3.000171422958374
2、无参装饰器(有位置参数)
1 #为定义可以传值的函数,添加计时的装饰器,此时要注意函数和装饰器中的位置参数传值的问题!!! 2 import time 3 4 def timer(func): 5 def wrapper(*args,**kwargs): #有权接管,无权为空! 6 start_time = time.time() 7 func(*args,**kwargs) #home(name) 8 stop_time = time.time() 9 print("run time is %s"%(stop_time-start_time)) 10 return wrapper 11 12 @timer #index = timer(index) 13 def index(): 14 time.sleep(1.5) 15 print("welcome to beijing!") 16 17 @timer 18 def home(name): #wrapper('alex') 19 time.sleep(1) 20 print("welcome to %s home page"%name) 21 22 @timer 23 def auth(name,passwd): 24 time.sleep(0.5) 25 print(name,passwd) 26 27 @timer 28 def tell(): 29 print("---***---") 30 31 index() 32 home("alex") 33 auth("alex","alex3714") 34 tell()
执行结果如下:
1 welcome to beijing! 2 run time is 1.5000858306884766 3 welcome to alex home page 4 run time is 1.0000569820404053 5 alex alex3714 6 run time is 0.5010290145874023 7 ---***--- 8 run time is 0.0
3、无参装饰器(主函数带有返回值的情况!)
1 #给带有返回值的函数添加统计时间的装饰器! 2 3 import time 4 5 def timer(func): 6 def wrapper(*args,**kwargs): 7 start_time = time.time() 8 res = func(*args,**kwargs) #my_max(1,2) 9 stop_time = time.time() 10 print("run time is %s"%(stop_time-start_time)) 11 return res #先将所有的功能接收出来,然后在返回 12 return wrapper 13 14 @timer 15 def my_max(x,y): 16 time.sleep(2) 17 print("max:") 18 res = x if x>y else y 19 return res #函数的返回值! 20 res = my_max(1,2) # res = wrapper(1,2) 21 print(res)
执行结果如下:
1 max: 2 run time is 2.0001144409179688 3 2
4、装饰器的实质既然是函数的调用,那么上面介绍完无参的情况,现在举例介绍有参的情况。
有参装饰器(登陆认证)
1 #为主函数添加认证功能。主函数不变,在主函数上@*** 一个装饰器,装饰器是靠函数来实现。 2 #认证功能是在真正的函数调用之前添加上认证的功能,所以认证是在装饰器中添加。 3 #有参装饰器是在装饰器上添加区分,认证的时候,需要区分不同类型信息的来源(如:本地文件,数据库), 4 #所以在装饰器上就需要添加认证参数,以区分开认证的来源,执行认证的时候,会在认证主函数中进行逻辑操作。 5 def auth2(auth_type): #参数认证函数 6 def auth(func): 7 def wrapper(*args,**kwargs): #认证函数 8 if auth_type == "file": 9 name = input("username:") 10 passwd = input("passwd:") 11 if name == "song" and passwd =="123": 12 print("auth successful") 13 res = func(*args,**kwargs) 14 return res #认证成功之后源代码再运行。 15 else: 16 print("auth error") 17 elif auth_type == "sql": 18 print("不会!") 19 return wrapper 20 return auth 21 22 #@auth2(auth_type="sql") #调用 不同认证类型的参数 23 #def index(): #index = auth(index) 24 # print("welcome to index page") 25 26 @auth2(auth_type="file") #调用 不同认证类型的参数 27 def my_index(): 28 print("welcome to inexd page") 29 #index() 30 my_index()
执行结果如下:
1 username:song 2 passwd123 3 auth successful 4 welcome to inexd page
5、多个装饰器调用!实现主函数的登录认证功能
1 #多个装饰器调用! 2 #1、加上了统计函数的执行时间 3 #2、加上了认证功能,为避免重复登录认证,执行功能完成之后再判断登录状态。已登录则跳过,第一次登录会有登录信息的认证。 4 5 import time 6 current_login={'name':None,'login':False} 7 8 def timmer(func): 9 def wrapper(*args,**kwargs): 10 start_time=time.time() 11 res=func(*args,**kwargs) #my_max(1,2) 12 stop_time=time.time() 13 print('run time is %s' %(stop_time-start_time)) 14 return res 15 return wrapper 16 17 def auth2(auth_type='file'): 18 def auth(func): 19 # print(auth_type) 20 def wrapper(*args,**kwargs): 21 if current_login['name'] and current_login['login']: 22 res=func(*args,**kwargs) 23 return res 24 if auth_type == 'file': 25 name=input('username: ') 26 password=input('password: ') 27 if name == 'zhejiangF4' and password == 'sb945': 28 print('auth successfull') 29 res=func(*args,**kwargs) 30 current_login['name']=name 31 current_login['login']=True 32 return res 33 else: 34 print('auth error') 35 elif auth_type == 'sql': 36 print('还他妈不会玩') 37 return wrapper 38 return auth 39 40 @timmer 41 @auth2(auth_type='file') #@auth #index=auth(index) 42 def index(): 43 print('welcome to inex page') 44 45 @auth2() 46 def home(): 47 print('welcome to home page') 48 49 50 51 #调用阶段 52 index() 53 home()
执行结果如下:
1 username: zhejiangF4 2 password: sb945 3 auth successfull 4 welcome to inex page 5 run time is 10.760615348815918 6 welcome to home page