内容简介:python--装饰器详解
Python---装饰器详解
定义:
本质上是一个函数。作用是用来装饰另一个函数(即被装饰函数),给被装饰函数添加功能。前提是不能改变被装饰函数的源代码和调用方式。这样的一个函数称之为装饰器。
解析:
下面我们话不多说,直接用代码说明。下面是一个函数。
1 def add(): 2 b=1+2 3 print(b 4 5 add()
程序输出:
————————
3
————————
现在我要给这个函数增加一个解释性的句子,如下,我们可以编写一个装饰器:
1 #原函数
2 def add():
3 a=1+2
4 print(a)
5 #装饰器
6 def decorator(func):
7 def warpper():
8 print("1+2的结果是:")
9 func()
10 return warpper
11 #注意此句
12 add=decorator(add)
13 #调用函数
14 add()
程序输出:
——————————
1+2的结果是:
3
——————————
这样我们就成功的达成了我们的目的。这里要注意第12行的这一句,这一句是将add这个函数对象传入了decorator()函数,返回的是一个新函数变量,这个新函数对象又重新赋值给add,这样就可以保证不改变被装饰函数的调用方式不变。在 Python 语法中有一种更优雅的方式可以代替第十二行的语句。如下:
1 #装饰器
2 def decorator(func):
3 def warpper():
4 print("1+2的结果是:")
5 func()
6 return warpper
7
8 #add=decorator(add)
9 #原函数
10 @decorator#换成@符号
11 def add():
12 a=1+2
13 print(a)
14 #调用函数
15 add()
在被装饰函数前面直接加上“@xxx”(xxx为装饰器函数名)即可
被装饰函数有参数怎么办?
如果被装饰器函数有参数呢?该怎们班?不用担心,我们可以用不定参数的形式来收集参数。实例代码如下:
1 def decorator(func):
2 def warpper(*args,**kwargs):
3 print("相加的结果是:")
4 func(*args,**kwargs)
5 return warpper
6
7 @decorator
8 def add(x,y):
9 a=x+y
10 print(a)
11
12 add(2,3)
程序输出: —————————————————— 相加的结果是: 5 —————————————————— 如上,我们给包装函数加上接收参数,然后传给func()函数就行了。这样不管被装饰函数有怎样的参数都不怕了。
下面写一个页面验证的装饰器。
大家知道有些网站的一部分页面是要求用户登录之后才可以访问的,比如下面的三个函数(分别代表三个页面):
1 def index():
2 print("welcome to the index page")
3 def home():
4 print("welcome to the home page")
5 def bbs():
6 print("welcome to the bbs page")
7 return "I am the return contents"
假如说现在我们要给home页面和bbs页面加上验证,显然现在更改源代码是不可行的。这个时候我们可以用装饰器,如下:
1 username,passwd="jack","abc123"#模拟一个已登录用户
2 def decorator(func):
3 def warpper(*args,**kwargs):
4 Username=input("Username:").strip()
5 password=input("Password:").strip()
6 if username==Username and passwd==password:
7 print("Authenticate Success!")
8 func(*args,**kwargs)
9 else:
10 exit("Username or password is invalid!")
11 return warpper
12
13 def index():
14 print("welcome to the index page")
15 @decorator
16 def home():
17 print("welcome to the home page")
18 @decorator
19 def bbs():
20 print("welcome to the bbs page")
21 return "I am the return contents"
22
23 index()
24 home()
25 bbs()
程序结果:
————————
welcome to the index page #index页面未验证直接可以登入
Username:jack
Password:abc123
Authenticate Success! #登录的而情形
welcome to the home page
Username:jack #密码或用户名错误的情形
Password:123
Username or password is invalid!
————————
我们注意到bbs()是有返回值的,如果我们把上述代码的最后一句(第25行)改为“print(bbs())”之后再看看他的输出结果:
————————
welcome to the index page
Username:jack
Password:abc123
Authenticate Success!
welcome to the home page
Username:jack
Password:abc123
Authenticate Success!
welcome to the bbs page
None
#返回值能么成None了???
————————
What happened! bbs()的返回值打印出来竟然是None。怎么会这样?这样的话不就改变了被装饰函数的源代码了吗?怎样才能解决呢?
我们来分析一下:
我们执行bbs函数其实就相当于执行了装饰器里的wrapper函数,仔细分析装饰器发现wrapper函数却没有返回值,所以为了让他可以正确保证被装饰函数的返回值可以正确返回,那么需要对装饰器进行修改:
1 username,passwd="jack","abc123"#模拟一个已登录用户
2 def decorator(func):
3 def warpper(*args,**kwargs):
4 Username=input("Username:").strip()
5 password=input("Password:").strip()
6 if username==Username and passwd==password:
7 print("Authenticate Success!")
8 return func(*args,**kwargs)#在这里加一个return就行了
9 else:
10 exit("Username or password is invalid!")
11 return warpper
12
13 def index():
14 print("welcome to the index page")
15 @decorator
16 def home():
17 print("welcome to the home page")
18 @decorator
19 def bbs():
20 print("welcome to the bbs page")
21 return "I am the return contents"
22
23 index()
24 home()
25 bbs()
如图加上第8行的return就可以解决了。下面我们在看看改后的程序输出:
————————
welcome to the index page
Username:jack
Password:abc123
Authenticate Success!
welcome to the home page
Username:jack
Password:abc123
Authenticate Success!
welcome to the bbs page
I am the return contents #bbs()的返回值得到了正确的返回
——-——————
好了,返回值的问题解决了.
既然装饰器是一个函数,那装饰器可以有参数吗?
答案是肯定的。我们同样可以给装饰器加上参数。比如还是上面的三个页面函数作为例子,我们可以根据不同页面的验证方式来给程序不同的验证,而这个验证方式可以以装饰器的参数传入,这样我们就得在装饰器上在嵌套一层函数 了:
1 username,passwd="jack","abc123"#模拟一个已登录用户
2 def decorator(auth_type):
3 def out_warpper(func):
4 def warpper(*args,**kwargs):
5 Username=input("Username:").strip()
6 password=input("Password:").strip()
7 if auth_type=="local":
8 if username==Username and passwd==password:
9 print("Authenticate Success!")
10 return func(*args,**kwargs)
11 else:
12 exit("Username or password is invalid!")
13 elif auth_type=="unlocal":
14 print("HERE IS UNLOCAL AUTHENTICATE WAYS")
15 return warpper
16 return out_warpper
17
18 def index():
19 print("welcome to the index page")
20 @decorator(auth_type="local")
21 def home():
22 print("welcome to the home page")
23 @decorator(auth_type="unlocal")
24 def bbs():
25 print("welcome to the bbs page")
26 return "I am the return contents"
27
28 index()
29 home()
30 bbs()
输出:
————————
welcome to the index page
Username:jack
Password:abc123
Authenticate Success!
welcome to the home page
Username:jack
Password:abc123
HERE IS UNLOCAL AUTHENTICATE WAYS
————————
可见,程序分别加入了第2行和第16行和中间的根据auth_type参数的判断的相关内容后, 就解决上述问题了。对于上面的这一个三层嵌套的相关逻辑,大家可以在 pycharm里头加上断点,逐步调试,便可发现其中的道理。
总结
要想学好迭代器就必须理解一下三条:
1.函数即变量(即函数对象的概念)
2.函数嵌套
3.函数式编程
作者:彭前超(QQ:3480487308)
时间:2017/6/10 23:09
转载请注明出处,谢谢合作。本人另有Python视频教程,想要的qq联系,非诚勿扰.
以上所述就是小编给大家介绍的《python--装饰器详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Python装饰器(decorator)定义与用法详解
- 装饰器与元数据反射(1)方法装饰器
- 草根学Python(十六) 装饰器(逐步演化成装饰器)
- 一文读懂 JS 装饰器,这是一个会打扮的装饰器
- 装饰器与元数据反射(2)属与类性装饰器
- Python装饰器
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Rationality for Mortals
Gerd Gigerenzer / Oxford University Press, USA / 2008-05-02 / USD 65.00
Gerd Gigerenzer's influential work examines the rationality of individuals not from the perspective of logic or probability, but from the point of view of adaptation to the real world of human behavio......一起来看看 《Rationality for Mortals》 这本书的介绍吧!