timeit --- 測量小量程式片段的執行時間¶
原始碼:Lib/timeit.py
該模組提供了一種對少量 Python 程式碼進行計時的簡單方法。它有一個命令列介面和一個可呼叫介面,它避免了許多測量執行時間的常見陷阱。另請參閱由 O'Reilly 出版的 Python 錦囊妙計 (Python Cookbook) 第二版中 Tim Peters 所寫的「演算法」章節的介紹。
基礎範例¶
以下範例展示了如何使用命令列介面來比較三個不同的運算式:
$ python -m timeit "'-'.join(str(n) for n in range(100))"
10000 loops, best of 5: 30.2 usec per loop
$ python -m timeit "'-'.join([str(n) for n in range(100)])"
10000 loops, best of 5: 27.5 usec per loop
$ python -m timeit "'-'.join(map(str, range(100)))"
10000 loops, best of 5: 23.2 usec per loop
這可以透過 Python 介面來實現:
>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.3018611848820001
>>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000)
0.2727368790656328
>>> timeit.timeit('"-".join(map(str, range(100)))', number=10000)
0.23702679807320237
也可以在 Python 介面傳遞可呼叫物件:
>>> timeit.timeit(lambda: "-".join(map(str, range(100))), number=10000)
0.19665591977536678
Python 介面¶
該模組定義了三個便利函式和一個公開類別:
- timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000, globals=None)¶
使用給定的陳述式、setup 程式碼和 timer 函式建立一個
Timer實例,並執行其timeit()方法 number 次。可選的 globals 引數指定會在其中執行程式碼的命名空間。在 3.5 版的變更: 新增 globals 選用參數。
- timeit.repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=5, number=1000000, globals=None)¶
使用給定的陳述式、setup 程式碼和 timer 函式建立一個
Timer實例,並使用給定的 repeat 計數和 number 來運行其repeat()方法。可選的 globals 引數指定會在其中執行程式碼的命名空間。在 3.5 版的變更: 新增 globals 選用參數。
在 3.7 版的變更: repeat 的預設值從 3 更改為 5。
- timeit.default_timer()¶
預設計時器始終為 time.perf_counter(),會回傳浮點秒數。另一種方法是 time.perf_counter_ns,會回傳整數奈秒。
在 3.3 版的變更:
time.perf_counter()現在是預設計時器。
- class timeit.Timer(stmt='pass', setup='pass', timer=<timer function>, globals=None)¶
用於計時小程式碼片段執行速度的類別。
建構函式接受一個要計時的陳述式、一個用於設定的附加陳述式和一個計時器函式。兩個陳述式都預設為
'pass';計時器函式會與平台相依(請參閱模組文件字串 (doc string))。stmt 和 setup 還可以包含由;或換行符號分隔的多個陳述式,只要它們不包含多行字串文字即可。預設情況下,該陳述式將在 timeit 的命名空間內執行;可以透過將命名空間傳遞給 globals 來控制此行為。要測量第一個陳述式的執行時間,請使用
timeit()方法。repeat()和autorange()方法是多次呼叫timeit()的便捷方法。setup 的執行時間不包含在總體運行計時中。
stmt 和 setup 參數還可以接受無需引數即可呼叫的物件。這會把對它們的呼叫嵌入到計時器函式中,然後由
timeit()去執行。請注意,在這種情況下,因有額外的函式呼叫,時間開銷 (timing overhead) 會稍大一些。在 3.5 版的變更: 新增 globals 選用參數。
- timeit(number=1000000)¶
主陳述式執行 number 次的時間。這將執行一次設定陳述式,然後回傳多次執行主陳述式所需的時間。預設計時器以浮點形式回傳秒數,引數是迴圈的次數,預設為一百萬次。要使用的主陳述式、設定陳述式和計時器函式會被傳遞給建構函式。
- autorange(callback=None)¶
自動決定呼叫
timeit()次數。這是一個便捷函式,它重複呼叫
timeit()以使得總時間 >= 0.2 秒,再回傳最終結果(迴圈數、該迴圈數所花費的時間)。它以 1、2、5、10、20、50... 的順序遞增數字來呼叫timeit()直到所用時間至少為 0.2 秒。如果有給定 callback 且不是
None,則每次試驗後都會使用兩個引數來呼叫它:callback(number, time_taken)。在 3.6 版被加入.
- repeat(repeat=5, number=1000000)¶
呼叫
timeit()數次。這是一個方便的函式,它會重複呼叫
timeit()並回傳結果列表。第一個引數指定呼叫timeit()的次數,第二個引數指定timeit()的 number 引數。備註
人們很容易根據結果向量來計算出平均值和標準差並將其作為依歸,然而這並不是很有用。在典型情況下,最低值給出了機器運行給定程式碼片段的速度的下限;結果向量中較高的值通常不是由 Python 速度的變化所引起,而是由干擾計時精度的其他行程造成的。因此,結果中的
min()可能是你應該感興趣的唯一數字。在解讀該數據後,你應該查看整個向量並以常識判讀而非單純仰賴統計資訊。在 3.7 版的變更: repeat 的預設值從 3 更改為 5。
- print_exc(file=None)¶
從計時程式碼印出回溯 (traceback) 的輔助函式。
典型用法:
t = Timer(...) # 在 try/except 之外 try: t.timeit(...