内容简介: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装饰器
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python基础教程
[挪] Magnus Lie Hetland / 袁国忠 / 人民邮电出版 / 2018-2-1 / CNY 99.00
本书包括Python程序设计的方方面面:首先从Python的安装开始,随后介绍了Python的基础知识和基本概念,包括列表、元组、字符串、字典以及各种语句;然后循序渐进地介绍了一些相对高级的主题,包括抽象、异常、魔法方法、属性、迭代器;此后探讨了如何将Python与数据库、网络、C语言等工具结合使用,从而发挥出Python的强大功能,同时介绍了Python程序测试、打包、发布等知识;最后,作者结合......一起来看看 《Python基础教程》 这本书的介绍吧!