有時候我們很希望看到程序中某個函數或某個代碼段的耗時情況,那么該如何辦呢?本文用兩種方式實現了代碼計時器的功能,第一種方式是采用裝飾器來實現,第二種方式采用上下文管理器實現。
其實計算代碼的運行時間,最朴素的想法就是先記錄下來某段代碼剛開始運行時的時間,等到運行完之后,再看一下結束時的時間,最后和開始運行時的時間求個差值,就是這段代碼所花費的時間。
下面兩種計時器的實現方式就是用到這樣一種非常簡單的方法。
用裝飾器實現函數計時器
# coding:utf-8
from functools import wraps
import time
def func_timer(function):
'''
用裝飾器實現函數計時
:param function: 需要計時的函數
:return: None
'''
@wraps(function)
def function_timer(*args, **kwargs):
print '[Function: {name} start...]'.format(name = function.__name__)
t0 = time.time()
result = function(*args, **kwargs)
t1 = time.time()
print '[Function: {name} finished, spent time: {time:.2f}s]'.format(name = function.__name__,time = t1 - t0)
return result
return function_timer
@func_timer
def test(x,y):
s = x + y
time.sleep(1.5)
print 'the sum is: {0}'.format(s)
if __name__ == '__main__':
test(1,2)
# 輸出結果
'''
[Function: test start...]
the sum is: 3
[Function: test finished, spent time: 1.50s]
'''
用上下文管理器實現代碼段計時器
上下文管理器其實是一個實現了__enter__
和__exit__
兩個特殊方法的對象,可以用with語法調用。可以參照操作文件的with oepn
操作,比如:
with open('data.txt','r') as fin:
data = fin.read()
使用with上下文管理器操作文件的好處就是,不用擔心文件使用完之后忘記關閉,上下文管理器會自動幫你關閉。
那么下面就用上下文管理器來實現一個代碼段計時器:
# coding:utf-8
from functools import wraps
import time
class MyTimer(object):
'''
用上下文管理器計時
'''
def __enter__(self):
self.t0 = time.time()
def __exit__(self, exc_type, exc_val, exc_tb):
print '[finished, spent time: {time:.2f}s]'.format(time = time.time() - self.t0)
def test(x,y):
s = x + y
time.sleep(1.5)
print 'the sum is: {0}'.format(s)
if __name__ == '__main__':
with MyTimer() as t:
test(1,2)
time.sleep(1)
print 'do other things'
# 輸出:
'''
the sum is: 3
do other things
[finished, spent time: 2.53s]
'''
總結
可以看出,上述兩種計時器的實現方式各有優缺點,用裝飾器實現的計時器優點是使用起來非常方便,給要計時的函數加一個裝飾器即可,但不足之處是無法對一個代碼片段進行計時。而用上下文管理器實現的計時器就可以對任意一個代碼段進行計時,彌補了裝飾器計時器的缺陷。
具體用哪種計時器,還是要根據實際情況來選擇。