zoukankan      html  css  js  c++  java
  • Python装饰器举例分析

    概述

    装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。

    我们要需要一个能测试函数运行时间的decorator,可以定义如下:

    def timer(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            end_time = time.time()
            print("Run time is: %s" % (end_time - start_time))
            return res
        return wrapper
    

    因为它是一个decorator,所以接受一个函数作为参数,并返回一个函数。我们要借助Python的@语法,把decorator置于函数的定义处:

    @timer
    def fun():
        time.sleep(1)
        print("This is a test")
        return "OK"
    

    运行结果就是:

    This is a test
    Run time is: 1.0000572204589844
    OK
    

    把@timer放在fun()处就相当于执行了语句:

    fun = timer(fun)
    

    如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,比如加上名字:

    def timer(name):
        def decorator(func):
            def wrapper(*args, **kwargs):
                start_time = time.time()
                res = func(*args, **kwargs)
                end_time = time.time()
                print("Name is: %s ; Run time is: %s" % (name, (end_time - start_time)))
                return res
            return wrapper
        return decorator
    

    调用及结果显示如下:

    @timer("Lance#")
    def fun():
        time.sleep(1)
        print("This is a test")
        return "OK"
    
    This is a test
    Name is: Lance# ; Run time is: 1.0000572204589844
    OK
    

    和两层嵌套的decorator相比,三层嵌套的效果是这样的:

    fun = timer("Lance#")(fun)
    

    因为函数也是对象,它也有__name__等属性。
    在未加装饰器之前的fun()函数,调用 fun的__name__属性结果是 'fun',但经过decorator装饰之后的函数,它们的__name__已经从原来的'fun'变成了'wrapper'

    所以,需要把原始函数的__name__等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

    Python内置的functools.wraps就可以完成这个任务,所以,一个完整的decorator的写法如下:

    import functools
    
    def timer(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            res = func(*args, **kwargs)
            end_time = time.time()
            print("Run time is: %s" % (end_time - start_time))
            return res
        return wrapper
    

    整体代码如下:

    __Author__ = "Lance#"
    
    # -*- coding = utf-8 -*-
    
    import time
    import functools
    
    def timer(name):
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kwargs):
                start_time = time.time()
                res = func(*args, **kwargs)
                end_time = time.time()
                print("Name is: %s ; Run time is: %s" % (name, (end_time - start_time)))
                return res
            return wrapper
        return decorator
    
    @timer("Lance#")
    def fun():
        time.sleep(1)
        print("This is a test")
        return "OK"
    
    if __name__ == '__main__':
        print(fun())
    
  • 相关阅读:
    python3笔记二十二:正则表达式之函数
    python3笔记二十一:时间操作datetime和calendar
    python3笔记二十:时间操作time
    python3笔记十七:python文件读写
    Spring常用注解
    Pytorch实现卷积神经网络CNN
    Keras实现autoencoder
    Keras实现LSTM
    TensorFlow实现CNN
    Recurrent Neural Networks vs LSTM
  • 原文地址:https://www.cnblogs.com/GyForever1004/p/8372228.html
Copyright © 2011-2022 走看看