• 装饰器--万能传参


    装饰器的万能传参(*args,**kwargs)

    案例

    一、环境:以上为线上代码,需要添加1个统计执行时间的功能。线上代码如下:

     1 #!/usr/bin/env python
     2 # -*- coding:utf8 -*-
     3 # Author:Dong Ye
     4 
     5 import  time
     6 
     7 
     8 def test1():
     9     time.sleep(3)
    10     print('in the test1')
    11 def test2():
    12     time.sleep(3)
    13     print('in the test2')
    14 
    15 
    16 test1()
    17 test2()

    二、需求:在不修改源代码(test1 & test2)和原代码调用方式的情况下,给test1新增这个功能。

    三、思路:

    1、结合装饰器的特点:高阶函数 + 嵌套函数 =装饰器
    2、使用嵌套函数把新增功能和源代码结合起来,并返回嵌套函数的内存地址。
    3、通过高阶函数把内存地址返回,然后重新覆盖掉test1的函数名。

     

    代码实现1

    一、操作步骤:

    1、先定义个高阶函数的decorator。
    2、嵌套函数将高阶函数的内存地址返回给test1。
    3、在高阶函数中调用test1的函数体与新增结果结合。

    实例:(以下是装饰器的执行顺序)

     1 def timer(func):  #2、timer(test1)  func = test1
     2     def deco():   #3、在内存里定义了一个变量
     3         start_time = time.time()  #7、执行开始时间
     4         func()                    #8、func()执行,其实就是执行了原代码test1
     5         stop_time = time.time()   #9、执行结束时间
     6         print('the func run time is %s' % (stop_time-start_time))  #10、打印出test1的执行时间
     7     return deco   #4、 返回deco函数的内存地址
     8 
     9 test1 = timer(test1)  #1、调用timer函数,将test1的变量传给func
    10                       #5、将deco的内存地址返回给test1
    11 test1()   #6、执行test1(),其实是执行了deco()函数体
    12 
    13 #test2 = timer(test2)
    14 #test2()

    代码实现2

    优化第一个装饰器代码(无参数传值):
    1、由于第一个装饰器是按照函数调用传值的方式展现的。
    2、如果装饰函数体过多则会显得装饰器很乱,不易读写

    优化后代码:

     1 import time        #1导入time模块
     2 def timer(func):   #2相当于在内存中定义一个变量    #4 @timer其实是tist1 = timer(test1),所以会调用到timer函数。
     3     def deco():    #5、将func定义成一个高阶函数    #8 在调用test1时,实际调用的是deco函数
     4         start_time = time.time()  #9 获取当前值
     5         func()   #10 调用源代码函数
     6         stop_time = time.time()  #14返回装饰器,继续下一个功能
     7         print('the func run time is %s'%(stop_time-start_time))  #15打印
     8     return deco   #6返回高阶函数的内存地址
     9 
    10 @timer  #这个表示test1 = timer(test1)   #3指定需要装饰的源代码
    11 def test1():   #11 调用源代码
    12     time.sleep(3)  #12 调用源代码
    13     print('in the test1') #13 调用源代码
    14 
    15 
    16 
    17 test1()   #7 调用test1(),实际执行的是装饰器中的deco。

    代码实现3

    一旦这个函数被装饰器装饰,那么这个函数将会被重新赋值,赋值成装饰器函数的内存函数。

     1 #定义嵌套函数
     2 def timer(func):   #定义timer函数为了传递test参数 func = test1  
     3     def deco(*args,**kwargs):   #定义功能函数    #由于在工作中产的参数和参数功能不统一,所以在deco()和func()函数中使用2个万能参数*args和**wargs;
     4         start_time=time.time()
     5         func(*args,**kwargs)    #执行test传参的函数 func() = test1()
     6         stop_time = time.time()
     7         print('the func run time is %s' % (stop_time-start_time))
     8     return deco   #返回deco函数的内存地址
     9 
    10 
    11 @timer    #test1 = timer(test1) = deco  test1() = deco()   
    12 def test1():
    13     time.sleep(3)
    14     print('in the test1')
    15 
    16 @timer  #test2 = timer(test2) = deco   test2(name,age) = deco(name,age)
    17 def test2(name,age):
    18     time.sleep(3)
    19     print('name: %s   age: %s' % (name, age))
    20 
    21 test1()   # test1() = deco()
    22 test2('dongye',33)    #test2(name,age) = deco(name,age)
    23 
    24 
    25 
    26 # 注释:
    27 # test2的赋值是嵌套函数timer(test2)返回来的deco的内存地址;
    28 # 在调用test2()的时候,实际上是在调用deco()函数
    29 # 需要注意的2个地方:
    30 #     1、调用test2()函数时,传值的neme和age实际是传值给了deco嵌套函数中;
    31 #     2、如果deco()函数与内部执行的func()中,没有指定形参,则会报错;
    32 #     3、由于在工作中产的参数和参数功能不统一,所以在deco()和func()函数中使用2个万能参数*args和**wargs;
  • 相关阅读:
    bootstrap媒体查询
    Qt用Zip压缩文件夹的一些坑
    QCanvasItem介绍-QT3
    C盘无损扩容
    ArcGis连接oracle失败:ORA-6413:连接未打开
    通过ArcMap发布服务
    windows系统下使用cd命令
    C语言运算符优先级
    c/c++ 指针
    c++数组易错点总结
  • 原文地址:https://www.cnblogs.com/abobo/p/8064613.html
Copyright © 2020-2023  润新知