zoukankan      html  css  js  c++  java
  • Python装饰器Decorators

    def hi(name="yasoob"):
        return "hi " + name
    print(hi())
    # 我们甚至可以将一个函数赋值给一个变量,比如
    greet=hi
    # 我们这里没有在使用小括号,因为我们并不是在调用hi函数
    # 而是在将它放在greet变量里头。我们尝试运行下这个
    print(greet(),greet,sep='
    ')
    gre=hi()
    print(gre)
    '''
    以上输出为:
    hi yasoob
    hi yasoob
    <function hi at 0x00000240E0E71160>
    hi yasoob
    '''
    # 如果我们删掉旧的hi函数,看看会发生什么!
    del hi
    # print(hi())
    # outputs: NameError
    print(greet())
    # outputs: 'hi yasoob'
    全部输出为:
    '''
    hi yasoob
    hi yasoob
    <function hi at 0x00000240E0F3DEE0>
    hi yasoob
    hi yasoob
    '''
    

    参考:https://www.runoob.com/w3cnote/python-func-decorators.html

    在函数中定义函数

    刚才那些就是函数的基本知识了。我们来让你的知识更进一步。在 Python 中我们可以在一个函数中定义另一个函数:

    def hi(name="yasoob"):
        print("now you are inside the hi() function")
    
        def greet1():
            return "now you are in the greet1() function"
    
        def welcome():
            return "now you are in the welcome() function"
    
        print(greet1())
        print(welcome())
        print("now you are back in the hi() function")
    
    print(hi())
    # output:now you are inside the hi() function
    #       now you are in the greet1() function
    #       now you are in the welcome() function
    #       now you are back in the hi() function
    #       None
    
    # 上面展示了无论何时你调用hi(), greet1()和welcome()将会同时被调用。
    # 然后greet1()和welcome()函数在hi()函数之外是不能访问的,比如:
    greet1()
    # outputs: NameError: name 'greet1' is not defined
    

    那现在我们知道了可以在函数中定义另外的函数。也就是说:我们可以创建嵌套的函数。现在你需要再多学一点,就是函数也能返回函数。  

    从函数中返回函数

    其实并不需要在一个函数里去执行另一个函数,我们也可以将其作为输出返回出来:

    def hi(name="yasoob"):
        def greet1():
            return "now you are in the greet1() function"
     
        def welcome():
            return "now you are in the welcome() function"
     
        if name == "yasoob":
            return greet1
        else:
            return welcome
     
    a = hi()
    print(a)
    #outputs: <function greet at 0x7f2143c01500>
     
    #上面清晰地展示了`a`现在指向到hi()函数中的greet1()函数
    #现在试试这个
     
    print(a())
    #outputs: now you are in the greet1() function
    

    再次看看这个代码。在 if/else 语句中我们返回 greet 和 welcome,而不是 greet() 和 welcome()。为什么那样?这是因为当你把一对小括号放在后面,这个函数就会执行;然而如果你不放括号在它后面,那它可以被到处传递,并且可以赋值给别的变量而不去执行它。 你明白了吗?让我再稍微多解释点细节。

    当我们写下 a = hi(),hi() 会被执行,而由于 name 参数默认是 yasoob,所以函数 greet 被返回了。如果我们把语句改为 a = hi(name = "ali"),那么 welcome 函数将被返回。我们还可以打印出hi()(),这会输出 now you are in the greet() function

    def hi(name="yasoob"):
        def greet1():
            return "now you are in the greet1() function"
    
        def welcome():
            return "now you are in the welcome() function"
    
        if name == "yasoob":
            return greet1
        else:
            return welcome
    
    
    a = hi()
    print(a,hi()(),sep='
    ')
    
    输出为:
    <function hi.<locals>.greet1 at 0x00000240E0EAAAF0>
    now you are in the greet1() function
    

    将函数作为参数传给另一个函数

    def hi():
        return "hi yasoob!"
     
    def doSomethingBeforeHi(func):
        print("I am doing some boring work before executing hi()")
        print(func())
     
    doSomethingBeforeHi(hi)
    #outputs:I am doing some boring work before executing hi()
    #        hi yasoob!
    

    现在你已经具备所有必需知识,来进一步学习装饰器真正是什么了。装饰器让你在一个函数的前后去执行代码。

    你的第一个装饰器

    在上一个例子里,其实我们已经创建了一个装饰器!现在我们修改下上一个装饰器,并编写一个稍微更有用点的程序:

    def a_new_decorator(a_func):
     
        def wrapTheFunction():
            print("I am doing some boring work before executing a_func()")
     
            a_func()
     
            print("I am doing some boring work after executing a_func()")
     
        return wrapTheFunction
     
    def a_function_requiring_decoration():
        print("I am the function which needs some decoration to remove my foul smell")
     
    a_function_requiring_decoration()
    #outputs: "I am the function which needs some decoration to remove my foul smell"
     
    a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
    #now a_function_requiring_decoration is wrapped by wrapTheFunction()
     
    a_function_requiring_decoration()
    #outputs:I am doing some boring work before executing a_func()
    #        I am the function which needs some decoration to remove my foul smell
    #        I am doing some boring work after executing a_func()
    

    你看明白了吗?我们刚刚应用了之前学习到的原理。这正是 python 中装饰器做的事情!它们封装一个函数,并且用这样或者那样的方式来修改它的行为。

    现在你也许疑惑,我们在代码里并没有使用 @ 符号?那只是一个简短的方式来生成一个被装饰的函数。这里是我们如何使用 @ 来运行之前的代码:  

    @a_new_decorator
    def a_function_requiring_decoration():
        """Hey you! Decorate me!"""
        print("I am the function which needs some decoration to "
              "remove my foul smell")
     
    a_function_requiring_decoration()
    #outputs: I am doing some boring work before executing a_func()
    #         I am the function which needs some decoration to remove my foul smell
    #         I am doing some boring work after executing a_func()
     
    #the @a_new_decorator is just a short way of saying:
    a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
    

      

      

  • 相关阅读:
    SqlServer相关文章
    C#字典(Dictionary)相关文章记录
    Mysql相关文章
    Rabbitmq相关文章
    C#多线程之锁相关文章
    23种设计模式相关文章
    IdentityServer4之Consent与offline_access
    .netCore mvc 在javascript中读取属性中文乱码的问题
    基于 NET5的QQ扫码登录的第三方实现(无需注册开发者)
    Windows 操作系统开启长路径支持
  • 原文地址:https://www.cnblogs.com/Li-JT/p/15191263.html
Copyright © 2011-2022 走看看