从小例子中进入装饰器
统计一个函数执行耗时
-
原始版本
1 import time 2 3 # time模块有提供时间相关函数 4 def do_something(): 5 print("do_something") 6 time.sleep(0.5) # 让程序停止0.5秒模拟其它操作耗时 7 8 start = time.time() 9 do_something() 10 print(time.time() - start) 11 #result: 12 # do_something 13 # 0.5000283718109131
问题:上述代码可以完成这个功能,但之后会发现,如果我们要统计其它函数,就必须在每个函数前后加入相应代码
-
装饰器版本1(无参数)
1 import time 2 3 def execute_time(func): 4 def inner(): 5 start = time.time() 6 func() 7 print(time.time() - start) 8 9 return inner 10 11 # time模块有提供时间相关函数 12 def do_something(): 13 print("do_something") 14 time.sleep(0.5) # 让程序停止0.5秒模拟其它操作耗时 15 16 do_something = execute_time(do_something) 17 do_something() 18 #result: 19 # do_something 20 # 0.5000283718109131
从上述代码可以看到,使用了另一个函数execute_time()给我们要统计耗时的函数进行了包装,这时,这个execute_time()函数就叫做装饰器函数,而我们要统计的那个函数也就是do_something()函数就是被装饰的函数.问题:函数执行的时候实际上是调用的execute_time()函数中的inner()函数,这种方法虽然解决了原始版本的问题,但是当我们要统计的函数拥有返回值的时候,这时候我们获取不到返回值.
-
装饰器版本2(有固定参数)
import time def execute_time(func): def inner(do): start = time.time() result = func(do) print(time.time() - start) return result return inner # time模块有提供时间相关函数 def do_something(do): print("do_something", do) time.sleep(0.5) # 让程序停止0.5秒模拟其它操作耗时 return 'do_something over' do_something = execute_time(do_something) print(do_something('say hello')) # result: # do_something say hello # 0.5000283718109131 # do_something over
为了解决装饰器版本1的问题,我在inner()函数里面加了个返回值.问题:当被装饰函数的参数个数与inner()参数个数不同时,这个装饰器就不适用了
-
装饰器版本3(动态参数)
1 import time 2 3 def execute_time(func): 4 def inner(*args, **kwargs): 5 start = time.time() 6 result = func(*args, **kwargs) 7 print(time.time() - start) 8 return result 9 10 return inner 11 12 # time模块有提供时间相关函数 13 def do_something(do1,do2): 14 print("do_something", do1,do2) 15 time.sleep(0.5) # 让程序停止0.5秒模拟其它操作耗时 16 return 'do_something over' 17 18 do_something = execute_time(do_something) 19 print(do_something('say hello1','say hello2')) 20 # result: 21 # do_something say hello1 say hello2 22 # 0.5000283718109131 23 # do_something over
在第七天内容中有个知识点是动态参数,刚好可以解决这个问题
-
终极版本(语法糖@)
1 import time 2 3 def execute_time(func): 4 def inner(*args, **kwargs): 5 start = time.time() 6 result = func(*args, **kwargs) 7 print(time.time() - start) 8 return result 9 10 return inner 11 12 @execute_time 13 def do_something(do1,do2): 14 print("do_something", do1,do2) 15 time.sleep(0.5) # 让程序停止0.5秒模拟其它操作耗时 16 return 'do_something over' 17 18 # do_something = execute_time(do_something) 19 print(do_something('say hello1','say hello2')) 20 # result: 21 # do_something say hello1 say hello2 22 # 0.5000283718109131 23 # do_something over
对于装饰器,python内部给我们提供了语法糖支持.在需要被装饰的函数名上部使用[@装饰器函数名称]即可,简化上述代码18行