1 # -*-coding=utf-8 -*- 2 #实现一个函数执行后计算执行时间的功能 3 4 __author__ = ‘piay‘ 5 import time, functools 6 7 8 def foo(): 9 ‘‘‘ 10 定义一个普通函数 11 :return: 12 ‘‘‘ 13 print ‘this is foo‘ 14 15 16 foo() 17 18 ‘‘‘ 19 这里如果我们需要查看函数执行时间,修改为: 20 ‘‘‘ 21 22 23 def foo1(): 24 start_time = time.clock() 25 print ‘this is foo1‘ 26 end_time = time.clock() 27 print ‘执行时间为:‘, end_time - start_time 28 29 30 foo1() 31 32 ‘‘‘ 33 如果我们其他的函数也需要执行时间,或者这个函数不需要执行时间,那么我们就需要复制到其他的函数中去 34 这是一种最差的方法 35 ‘‘‘ 36 37 38 def foo3(): 39 print ‘this is foo3‘ 40 41 42 def timeit(func): 43 ‘‘‘ 44 我们可以考虑重新定义一个函数timeit,将foo的引用传递给他, 45 然后在timeit中调用foo并进行计时,这样,我们就达到了不改动foo定义的目的 46 :param func: 传入的函数 47 :return: 48 ‘‘‘ 49 start_time = time.clock() 50 func() 51 end_time = time.clock() 52 print ‘used:‘, end_time - start_time 53 54 55 timeit(foo3) 56 ‘‘‘ 57 这样写修改调用部分的代码。原本我们是这样调用的:foo3(),现在变成timeit(foo),这样的话,如果foo在N处都被调用了, 58 你就不得不去修改这N处的代码。或者更极端的,考虑其中某处调用的代码无法修改这个情况,比如:这个函数是你交给别人使用的。 59 ‘‘‘ 60 61 ‘‘‘ 62 想想办法不修改调用的代码;如果不修改调用代码,也就意味着调用foo()需要产生调用timeit(foo)的效果。我们可以想到将timeit赋值给foo, 63 但是timeit似乎带有一个参数……想办法把参数统一吧!如果timeit(foo)不是直接产生调用效果, 64 而是返回一个与foo参数列表一致的函数的话……就很好办了,将timeit(foo)的返回值赋值给foo,然后,调用foo()的代码完全不用修改! 65 ‘‘‘ 66 67 68 def foo4(): 69 print ‘this is foo4‘ 70 71 72 # 定义一个计时器,传入一个,并返回另一个附加了计时功能的方法 73 def timeit4(func): 74 # 定义一个内嵌的包装函数,给传入的函数加上计时功能的包装 75 def wrapper(): 76 start_time = time.clock() 77 func() 78 end_time = time.clock() 79 print ‘used:‘, end_time - start_time 80 81 # 将包装后的函数返回 82 return wrapper 83 84 85 foo_1 = timeit(foo4) 86 ‘‘‘ 87 上面的代码就类似装饰器了,可以修改为如下: 88 ‘‘‘ 89 90 91 @timeit4 # 定义上加上这一行与另外写foo = timeit(foo)完全等价 92 def foo5(): 93 print ‘this is foo5‘ 94 foo5() 95 96 97 ‘‘‘ 98 ----------------------------------------------- 99 使用functools.wraps(func)装饰器实现功能 100 ‘‘‘ 101 def timeit_3_for_wraps(func): 102 @functools.wraps(func) 103 def wrapper(): 104 start=time.clock() 105 func() 106 end=time.clock() 107 print ‘used:‘,end-start 108 return wrapper 109 110 @timeit_3_for_wraps 111 def foo6(): 112 print ‘this is foo6‘ 113 foo6()
这里实现一个完整的判断是否带参数的装饰器:
1 # -*-coding=utf-8 -*- 2 __author__ = ‘piay‘ 3 import functools, time 4 ‘‘‘ 5 一个函数执行前打印开始执行,执行完后打印执行完成,记录执行时间 6 ‘‘‘ 7 8 def log(text): 9 if callable(text): # 参数如果是函数,说明装饰器不带参传过来,text是一个函数 10 @functools.wraps(text) 11 def wrapper(*args, **kwargs): 12 start = time.clock() 13 print ‘这是不带参数的装饰器,开始执行‘ 14 f = text(*args, **kwargs) #执行本身的函数 text() 15 end = time.clock() 16 print "结束执行:", end - start 17 return f # 返还原函数 18 return wrapper 19 20 elif not callable(text): # text是参数,不是函数 21 def decarator(func): 22 @functools.wraps(func) 23 def warpper(*args, **kwargs): 24 start = time.clock() 25 print ‘这是不带参数的装饰器,开始执行,参数为:‘+text 26 f = func(*args, **kwargs) 27 end=time.clock() 28 print "结束执行:",end-start 29 return f #返还原函数 30 return warpper 31 return decarator 32 else: 33 print ‘请检查是否正确‘ 34 35 36 @log 37 def add1(x,y): 38 print x+y 39 40 @log(‘222‘) 41 def add2(x,y): 42 print x+y 43 44 add1(1,2) 45 add2(2,3)
执行结果:
D:\Python27\python.exe D:/Python/functools_study/完整的装饰器.py
这是不带参数的装饰器,开始执行
3
结束执行: 5.08444509009e-05
这是不带参数的装饰器,开始执行,参数为:222
5
结束执行: 2.49333364995e-05
Process finished with exit code 0