python基础第8天-装饰器函数

从小例子中进入装饰器

统计一个函数执行耗时

  • 原始版本

     1 import time
     2 
     3 # time模块有提供时间相关函数
     4 def do_something():
     5     print("do_something")
     6     time.sleep(0.5)  # 让程序停止0.5秒模拟其它操作耗时
     7 
     8 start = time.time()
     9 do_something()
    10 print(time.time() - start)
    11 #result:
    12 # do_something
    13 # 0.5000283718109131

    问题:上述代码可以完成这个功能,但之后会发现,如果我们要统计其它函数,就必须在每个函数前后加入相应代码

  • 装饰器版本1(无参数)

     1 import time
     2 
     3 def execute_time(func):
     4     def inner():
     5         start = time.time()
     6         func()
     7         print(time.time() - start)
     8 
     9     return inner
    10 
    11 # time模块有提供时间相关函数
    12 def do_something():
    13     print("do_something")
    14     time.sleep(0.5)  # 让程序停止0.5秒模拟其它操作耗时
    15 
    16 do_something = execute_time(do_something)
    17 do_something()
    18 #result:
    19 # do_something
    20 # 0.5000283718109131

    从上述代码可以看到,使用了另一个函数execute_time()给我们要统计耗时的函数进行了包装,这时,这个execute_time()函数就叫做装饰器函数,而我们要统计的那个函数也就是do_something()函数就是被装饰的函数.问题:函数执行的时候实际上是调用的execute_time()函数中的inner()函数,这种方法虽然解决了原始版本的问题,但是当我们要统计的函数拥有返回值的时候,这时候我们获取不到返回值.

  • 装饰器版本2(有固定参数)

    import time
    
    def execute_time(func):
        def inner(do):
            start = time.time()
            result = func(do)
            print(time.time() - start)
            return result
        return inner
    
    # time模块有提供时间相关函数
    def do_something(do):
        print("do_something", do)
        time.sleep(0.5)  # 让程序停止0.5秒模拟其它操作耗时
        return 'do_something over'
    
    do_something = execute_time(do_something)
    print(do_something('say hello'))
    # result:
    # do_something say hello
    # 0.5000283718109131
    # do_something over

    为了解决装饰器版本1的问题,我在inner()函数里面加了个返回值.问题:当被装饰函数的参数个数与inner()参数个数不同时,这个装饰器就不适用了

  • 装饰器版本3(动态参数)

     1 import time
     2 
     3 def execute_time(func):
     4     def inner(*args, **kwargs):
     5         start = time.time()
     6         result = func(*args, **kwargs)
     7         print(time.time() - start)
     8         return result
     9 
    10     return inner
    11 
    12 # time模块有提供时间相关函数
    13 def do_something(do1,do2):
    14     print("do_something", do1,do2)
    15     time.sleep(0.5)  # 让程序停止0.5秒模拟其它操作耗时
    16     return 'do_something over'
    17 
    18 do_something = execute_time(do_something)
    19 print(do_something('say hello1','say hello2'))
    20 # result:
    21 # do_something say hello1 say hello2
    22 # 0.5000283718109131
    23 # do_something over

    在第七天内容中有个知识点是动态参数,刚好可以解决这个问题

  • 终极版本(语法糖@)

     1 import time
     2 
     3 def execute_time(func):
     4     def inner(*args, **kwargs):
     5         start = time.time()
     6         result = func(*args, **kwargs)
     7         print(time.time() - start)
     8         return result
     9 
    10     return inner
    11 
    12 @execute_time
    13 def do_something(do1,do2):
    14     print("do_something", do1,do2)
    15     time.sleep(0.5)  # 让程序停止0.5秒模拟其它操作耗时
    16     return 'do_something over'
    17 
    18 # do_something = execute_time(do_something)
    19 print(do_something('say hello1','say hello2'))
    20 # result:
    21 # do_something say hello1 say hello2
    22 # 0.5000283718109131
    23 # do_something over

    对于装饰器,python内部给我们提供了语法糖支持.在需要被装饰的函数名上部使用[@装饰器函数名称]即可,简化上述代码18行

猜你喜欢

转载自www.cnblogs.com/zze46/p/9549737.html