zoukankan      html  css  js  c++  java
  • python 装饰器

    装饰器的实质就是一个函数,可以对其他函数进行装饰,在不改变原函数代码的基础上增加新的功能,调用方式也不改变。

    比如我们有两个函数sout1,sout2

    import time
    
    def sout1():
        time.sleep(1)
    	print("this is sout1")
    	
    	
    def sout2():
        time.sleep(2)
    	print("this is sout2")
        
    sout1()
    sout2()
    
    # 输出
    # this is sout1
    # this is sout2
    

    现在我想让每个方法执行完时输出运行需要的时间

    我们可以修改代码实现

    import time
    
    def sout1():
        start = time.time()
        time.sleep(1)
    	print("this is sout1")
        end = time.time()
        print("running time is",end-start)
    	
    	
    def sout2():
         start = time.time()
         time.sleep(2)
    	 print("this is sout2")
         end = time.time()
         print("running time is",end-start)
    
     """
    输出
    this is sout1
    running time is 1.0009281635284424
    this is sout2
    running time is 2.0002005100250244
    """
    

    一两个这样功能简单的还能改改,但要是许多函数,新增的功能复杂怎么办?

    最好使用装饰器来实现。

    在使用装饰前我们要先了解两个概念 高阶函数、嵌套函数

    高阶函数

    在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数:

    接受一个或多个函数作为输入

    输出一个函数

    我们已经定义了sout1这个函数

    sout1() // 会调用函数
    """
    输出
    this is sout1
    running time is 1.0009281635284424
    """
    print (sout)
    <function sout1 at 0x02CEB780>
    

    万物皆对象嘛

    所以函数也是对象

    sout1存的是地址 是对象的引用

    我们新增一个引用

    hello = sout1
    hello()
    
    """
    输出
    this is sout1
    running time is 1.0009281635284424
    """
    

    既然是对象 当然也能作为函数的参数和返回值

    例:

    def test(func):
        return func
    
    def sout():
        print("hello world!")
        
    a = test(sout)
    a()
    
    """
    输出
    hello world!
    """
    

    嵌套函数

    就是函数里面又定义一个函数

    例:

    def outer():
        print("hello")
        def inner():
            print("world!")
        inner()
    
    outer()
    
    """
    输出
    hello
    world!
    """
    

    实现

    新增功能(修改调用方式)

    既然可以把函数当作参数传入,那..

    我们不就可以把原有函数当作参数传进一个新的函数中,新增点功能在返回出来?

    import time
       
    def sout1():
        time.sleep(1)
        print("this is sout1")
       
       
    def decorate(func):
        start = time.time()
        func()
        end = time.time()
        print("running time is",end-start)
       
       
       decorate(sout1)
       
       """
       输出
       this is sout1
       running time is 1.0004260540008545
       """
               
    

    现在已经实现了不修改原有代码添加新功能了,但是调用方式和以前不一样了。

    新增功能(不修改调用方式)

    那怎么实现不修改原来的调用方式?还是sout1()进行调用?

    我们已经知道函数也可以和变量一样,给它一个新的引用,进行调用

    如:

    x = 1
    y = x
    print(y)
    """
    输出
    1
    """
    
    def sout1():
        time.sleep(1)
        print("this is sout1")
        
    hello = sout1
    hello()
    """
    输出
    this is sout1
    """
    

    那我们想办法让进行装饰的函数 **decorate() **也返回一个函数

    然后 sout1 = decorate(sout1)

    不就实现了sout1()

    新增功能而不修改原代码,原调用方式?

    所以我们可以把decorate()中的代码再封装一下

    def sout1():
        time.sleep(1)
        print("this is sout1")
    
    # 原decorate()
    # def decorate(func):
    #     start = time.time()
    #     func()
    #     end = time.time()
    #     print("running time is",end-start)
    
    #改为:
    def decorate(func):
        def inner():
            start = time.time()
            func()
            end = time.time()
            print("running time is",end-start)
        return inner
    
    
    sout1 = decorate(sout1)
    sout1()
    """
    输出
    this is sout1
    running time is 1.0003764629364014
    """
    

    成功!

    然而我们还是要在 原来的函数调用前

    添加类似语句 sout1 = decorate(sout1)

    这个事情python可以通过语法糖@来帮我们完成

    def decorate(func):
        def inner():
            start = time.time()
            func()
            end = time.time()
            print("running time is", end - start)
    
        return inner
    
    
    @decorate  # 等同于 sout1 = decorate(sout1)
    def sout1():
        time.sleep(1)
        print("this is sout1")
    
    
    sout1()
    

  • 相关阅读:
    解析XML
    事务
    js小工具
    plsql用过的流程语句
    查询语句
    存储过程
    用过的CRT命令
    mysql常用命令
    Spirng MVC demo 完整示例01 环境搭建
    jmeter多个http请求串联
  • 原文地址:https://www.cnblogs.com/hehecat/p/9263202.html
Copyright © 2011-2022 走看看