• Python3之装饰器


      参考:https://www.cnblogs.com/songyue/p/5196809.html

      例如以前写了一个简单的函数sum1如下

    def sum1():
        sum=1+2
        print(sum)
    
    
    sum1()
    print('函数名为',sum1.__name__)                    
    

      运行结果为

    3
    函数名为 sum1
    

      假如需要新加一个功能查看该函数运行执行了多长时间,可以导入时间模块记录开始时间及结束时间,用结束时间减开始时间及可得到运行时间,修改函数如下

    import time 
    import functools
    
    def sum1():
        start=time.time()
        sum=1+2
        print(sum)
        end=time.time()
        print("Time used:",end-start)
    
    sum1()
    print('函数名为',sum1.__name__)
    

      运行结果

    3
    Time used: 2.6464462280273438e-05
    函数名为 sum1
    

      可是还是许多函数需要增加运行时间的功能,难道一个个函数去改嘛,可以定义一个时间函数timeit将sum1作为参数传递给时间函数timeit在timeit里面调用sum1

    import time
    import functools
    
    def sum1():
        sum=1+2
        print(sum)
    
    def timeit(func):
        start=time.time()
        func()
        end=time.time()
        print('Time used:',end-start)
        
    timeit(sum1)
    

      运行结果

    3
    Time used: 2.574920654296875e-05
    

      可以运行,但是还是修改了一部分代码,把sum1()改成了timeit(sum1),直接运行sum1()还是不会打印运行时间,如果sum在N处被调用了,不得不去修改N处代码。所以需要将sum1()具有和timeit(sum1)一样的效果,于是将timeit赋值给sum1,可是timeit是有参数的,所以需要找个方法去统一参数,将timeit(sum1)发返回值(计算运行时间的函数)赋值给sum1

    import time
    import functools
    
    def sum1():
        sum=1+2
        print(sum)
    
    def timeit(func):
        def test():
            start=time.time()
            func()
            end=time.time()
            print('Time used:',end-start)
        return test
    
    sum1=timeit(sum1)
    #sum1为函数名需要加括号执行执行
    sum1()
    print('函数名为',sum1.__name__)
    

      执行结果

    3
    Time used: 3.0279159545898438e-05
    函数名为 test
    

      一个装饰器就做好了,我们只需要在定义sum1之后调用sum1之前,加上sum1=timeit(sum1),就可以达到计时的目的,这就是装饰器的概念,看起来像是sum1倍timeit装饰了,Python提供一个语法糖来降低字符输入量

    import time
    import functools
    
    
    def timeit(func):
        def test():
            start=time.time()
            func()
            end=time.time()
            print('Time used:',end-start)
        return test
    
    @timeit
    def sum1():
        sum=1+2
        print(sum)
    
    
    #sum1为函数名需要加括号执行执行
    sum1()
    print('函数名为',sum1.__name__)
    

      PS:这里的@timeit等价于sum1=timeit(sum1)

          执行结果

    3
    Time used: 2.8848648071289062e-05
    函数名为 test
    

      我们可以看到执行的函数名为test,因为返回的是test函数,需要把原始函数sum1的__name__属性复制到test()函数中,否则,有些依赖函数前面的代码执行就会出错,不需要编写test.__name__=func.__name__这样的代码,python内置的functools.wraps就是干这个事的,所以,一个完整的装饰器写法如下

    import time
    import functools
    
    
    def timeit(func):
        @functools.wraps(func)
        def test():
            start=time.time()
            func()
            end=time.time()
            print('Time used:',end-start)
        return test
    
    @timeit
    def sum1():
        sum=1+2
        print(sum)
    
    
    #sum1为函数名需要加括号执行执行
    sum1()
    print('函数名为',sum1.__name__)
    

      执行结果

    3
    Time used: 3.647804260253906e-05
    函数名为 sum1
    

      函数名为原始函数名sum1

      以上装饰器装饰函数为不带参数函数,假如需要装饰多个函数而有的函数带参数有的函数不带参数则需要编写一个通用装饰器

    import time
    import functools
    
    def timeit(func):
        @functools.wraps(func)
        def test(*args,**kw):
            start=time.time()
            func(*args,**kw)
            end=time.time()
            print('Time used:',end-start)
            #return func(*args,**kw)
        return test
    
    @timeit
    def sum1(s):
        print(s)
    
    sum1('hello world')
    print('函数名为',sum1.__name__)
    

      

      test()函数的参数定义是(*args, **kw),因此,test()函数可以接受任意参数的调用。在test()函数内在运行函数的前后加时间记录

  • 相关阅读:
    百度网盘怎么批量删除好友,百度网盘怎么群发消息
    百度网盘不能公开分享了怎么办,怎么批量提取链接?
    百度云/百度网盘私密分享统一设置密码
    pdf.js浏览中文pdf乱码的问题解决
    百度网盘自动更新资源、百度网盘自动更新链接、百度网盘自动更新内容、百度网盘自动更新文件夹、百度网盘怎么自动更新、百度网盘自动更新课件、百度网盘文件自动更新、百度网盘怎么更新文件
    邓西百度网盘批量转存高级版,支持增量更新资料
    邓西百度知道刷赞工具
    spark streaming 3: Receiver 到 submitJobSet
    spark streaming 2: DStream
    spark streaming 1: SparkContex
  • 原文地址:https://www.cnblogs.com/minseo/p/11081556.html
Copyright © 2020-2023  润新知