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()
View Code

执行结果如下:

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
原文地址:https://www.cnblogs.com/zh605929205/p/6690660.html