装饰器--万能传参

 

装饰器的万能传参(*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;

 

posted @ 2017-12-19 11:24  风之岚翔  阅读(1133)  评论(0编辑  收藏  举报