美文网首页
Python---装饰器详解

Python---装饰器详解

作者: coderST | 来源:发表于2017-10-24 11:18 被阅读29次

定义:

本质上是一个函数。作用是用来装饰另一个函数(即被装饰函数),给被装饰函数添加功能。前提是不能改变被装饰函数的源代码和调用方式。这样的一个函数称之为装饰器。

解析:

下面我们话不多说,直接用代码说明。下面是一个函数。

1 def add():
2     b=1+2
3     print(b)
4
5 add()
程序输出:
————————

3

————————
  • 现在我要给这个函数增加一个解释性的句子,如下,我们可以编写一个装饰器:
#原函数
def add():
    a=1+2
    print(a)  
#装饰器
def decorator(func):
    def warpper():
        print("1+2的结果是:")
        func()
    return warpper
#注意此句   
add=decorator(add)
#调用函数
add()

程序输出:

——————————

1+2的结果是:

3

——————————
  • 这样我们就成功的达成了我们的目的。这里要注意第12行的这一句,这一句是将add这个函数对象传入了decorator()函数,返回的是一个新函数变量,这个新函数对象又重新赋值给add,这样就可以保证不改变被装饰函数的调用方式不变。在Python语法中有一种更优雅的方式可以代替第十二行的语句。如下:
#装饰器
def decorator(func):
    def warpper():
        print("1+2的结果是:")
        func()
    return warpper

#add=decorator(add)
#原函数
@decorator#换成@符号
def add():
    a=1+2
    print(a)
#调用函数
add()

在被装饰函数前面直接加上“@xxx”(xxx为装饰器函数名)即可

被装饰函数有参数怎么办?

  • 如果被装饰器函数有参数呢?该怎们班?不用担心,我们可以用不定参数的形式来收集参数。实例代码如下:
def decorator(func):
    def warpper(*args,**kwargs):
        print("相加的结果是:")
        func(*args,**kwargs)
    return warpper

@decorator
def add(x,y):
    a=x+y
    print(a)

add(2,3)

程序输出:

——————————————————
相加的结果是:
5
——————————————————

如上,我们给包装函数加上接收参数,然后传给func()函数就行了。这样不管被装饰函数有怎样的参数都不怕了。

下面写一个页面验证的装饰器。

  • 大家知道有些网站的一部分页面是要求用户登录之后才可以访问的,比如下面的三个函数(分别代表三个页面):
def index():
    print("welcome to the index page")
def home():
    print("welcome to the home page")
def bbs():
    print("welcome to the bbs page")
    return "I am the return contents"
  • 假如说现在我们要给home页面和bbs页面加上验证,显然现在更改源代码是不可行的。这个时候我们可以用装饰器,如下:
username,passwd="jack","abc123"#模拟一个已登录用户
def decorator(func):
    def warpper(*args,**kwargs):
        Username=input("Username:").strip()
        password=input("Password:").strip()
        if username==Username and passwd==password:
            print("Authenticate Success!")
            func(*args,**kwargs)
        else:
            exit("Username or password is invalid!")
    return warpper

def index():
    print("welcome to the index page")
@decorator
def home():
    print("welcome to the home page")
@decorator
def bbs():
    print("welcome to the bbs page")
    return "I am the return contents"

index()
home()
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函数却没有返回值,所以为了让他可以正确保证被装饰函数的返回值可以正确返回,那么需要对装饰器进行修改:

username,passwd="jack","abc123"#模拟一个已登录用户
def decorator(func):
    def warpper(*args,**kwargs):
        Username=input("Username:").strip()
        password=input("Password:").strip()
        if username==Username and passwd==password:
            print("Authenticate Success!")
           return func(*args,**kwargs)#在这里加一个return就行了
        else:
            exit("Username or password is invalid!")
    return warpper

def index():
    print("welcome to the index page")
@decorator
def home():
    print("welcome to the home page")
@decorator
def bbs():
    print("welcome to the bbs page")
    return "I am the return contents"

index()
home()
bbs()
  • 如图加上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()的返回值得到了正确的返回

——-——————

好了,返回值的问题解决了.

既然装饰器是一个函数,那装饰器可以有参数吗?

  • 答案是肯定的。我们同样可以给装饰器加上参数。比如还是上面的三个页面函数作为例子,我们可以根据不同页面的验证方式来给程序不同的验证,而这个验证方式可以以装饰器的参数传入,这样我们就得在装饰器上在嵌套一层函数 了:
username,passwd="jack","abc123"#模拟一个已登录用户
def decorator(auth_type):
    def out_warpper(func):
        def warpper(*args,**kwargs):
            Username=input("Username:").strip()
            password=input("Password:").strip()
            if auth_type=="local":
                if username==Username and passwd==password:
                    print("Authenticate Success!")
                    return func(*args,**kwargs)
                else:
                    exit("Username or password is invalid!")
            elif auth_type=="unlocal":
                print("HERE IS UNLOCAL AUTHENTICATE WAYS")
        return warpper
    return out_warpper

def index():
    print("welcome to the index page")
@decorator(auth_type="local")
def home():
    print("welcome to the home page")
@decorator(auth_type="unlocal")
def bbs():
    print("welcome to the bbs page")
    return "I am the return contents"

index()
home()
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.函数式编程

原文链接:http://www.cnblogs.com/Akkbe-chao/p/6980332.html

相关文章

  • Python---装饰器详解

    定义: 本质上是一个函数。作用是用来装饰另一个函数(即被装饰函数),给被装饰函数添加功能。前提是不能改变被装饰函数...

  • python 装饰器

    参考链接:详解Python的装饰器

  • python中的装饰器

    python装饰器详解 Python装饰器学习(九步入门) 装饰器(decorator) 就是一个包装机(wrap...

  • 装饰器详解

    装饰器详解 简单实例教程 需要装饰的函数 装饰器的参数是方法名,就是被装饰的函数 被装饰的函数需要这样写 调用 结...

  • Python装饰器的另类用法

    原文出处: cicaday 之前有比较系统介绍过Python的装饰器(请查阅《详解Python装饰器》),本文算是...

  • 装饰器详解

    装饰器基本写法: 高级一点的装饰器 带参数的装饰器和类装饰器属于进阶的内容。在理解这些装饰器之前,最好对函数的闭包...

  • 装饰器详解

    第一次认识装饰器,其实是在学习 Python 的过程了解到的,后来在 JS 中也了解到有对应的实现。最近公司的 T...

  • 装饰器详解

    综述 装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,...

  • 装饰器 详解

  • java动态代理,python装饰器

    原文:java的动态代理机制详解 - xiaoluo501395377 - 博客园 python装饰器

网友评论

      本文标题:Python---装饰器详解

      本文链接:https://www.haomeiwen.com/subject/zustpxtx.html