1. 程式人生 > >python的計時函式——timeit模組

python的計時函式——timeit模組

關於 Python 程式碼優化你需要知道的最重要問題是,決不要自己編寫計時函式。

為一個很短的程式碼計時都很複雜。處理器有多少時間用於執行這個程式碼?有什麼在後臺執行嗎?每個現代計算機都在後臺執行持續或者間歇的程式。小小的疏忽可能破壞你的百年大計,後臺服務偶爾被 “喚醒” 在最後千分之一秒做一些像查收信件,連線計時通訊伺服器,檢查應用程式更新,掃描病毒,檢視是否有磁碟被插入光碟機之類很有意義的事。在開始計時測試之前,把一切都關掉,斷開網路的連線。再次確定一切都關上後關掉那些不斷檢視網路是否恢復的服務等等。

接下來是計時框架本身引入的變化因素。Python 直譯器是否快取了方法名的查詢?是否快取程式碼塊的編譯結果?正則表示式呢? 你的程式碼重複執行時有副作用嗎?不要忘記,你的工作結果將以比秒更小的單位呈現,你的計時框架中的小錯誤將會帶來不可挽回的結果扭曲。

Python 社群有句俗語:“Python 自己帶著電池。” 別自己寫計時框架。Python 2.3 具備一個叫做 timeit 的完美計時工具。

例 18.2. timeit 介紹

如果您還沒有下載本書附帶的樣例程式, 可以 下載本程式和其他樣例程式

>>> import timeit
>>> t = timeit.Timer("soundex.soundex('Pilgrim')",
... "import soundex")
>>> t.timeit()
8.21683733547
>>>
t.repeat(3, 2000000)
[16.48319309109, 16.46128984923, 16.44203948912]
1 timeit 模組定義了接受兩個引數的 Timer 類。兩個引數都是字串。第一個引數是你要計時的語句,這裡你計時的是以'Pilgrim'引數呼叫 Soundex 函式。傳遞給 Timer 的第二個引數是為第一個引數語句構建環境的匯入語句。從內部講,timeit 構建起一個獨立的虛擬環境,手工地執行建立語句 (匯入 soundex 模組),然後手工地編譯和執行被計時語句 (呼叫 Soundex 函式)。
2 只要有了 Timer 物件,最簡單的事就是呼叫 timeit()
,它呼叫你的函式一百萬次並返回所耗費的秒數。
3 Timer 物件的另一個主要方法是 repeat(),它接受兩個可選引數。第一個引數是重複整個測試的次數,第二個引數是每個測試中呼叫被計時語句的次數。兩個引數都是可選的,它們的預設值分別是 31000000repeat() 方法返回以秒記錄的每個測試迴圈的耗時列表。
提示
你可以在命令列使用 timeit 模組來測試一個已存在的 Python 程式,而不需要修改程式碼。在 http://docs.python.org/lib/node396.html 檢視文件中關於命令列選項的內容。

注意 repeat() 返回一個時間列表。由於 Python 計時器使用的處理器時間的微小變化 (或者那些你沒辦法根除的可惡的後臺程序),這些時間中幾乎不可能出現重複。你的第一想法也許是說:“讓我們求平均值獲得真實的資料。

事實上,那幾乎是確定錯誤的。你的程式碼或者 Python 直譯器的變化可能縮短耗時,那些沒辦法去除的可惡後臺程序或者其他 Python 直譯器以外的因素也許令耗時延長。如果計時結果之間的差異超過百分之幾,太多的可變因素使你沒法相信結果,如果不是這樣則可以取最小值而丟棄其他結果。

Python 有一個方便的 min 函式返回輸入列表中的最小值:

>>> min(t.repeat(3, 1000000))
8.22203948912
提示
timeit 模組只有在你知道哪段程式碼需要優化時使用。如果你有一個很大的 Python 程式並且不知道你的效能問題所在,檢視 hotshot 模組