新聞中心
timeit —- 測量小代碼片段的執(zhí)行時(shí)間
源碼: Lib/timeit.py

創(chuàng)新互聯(lián)專注于企業(yè)成都全網(wǎng)營銷、網(wǎng)站重做改版、珠山網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5技術(shù)、商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)公司、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為珠山等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
此模塊提供了一種簡單的方法來計(jì)算一小段 python 代碼的耗時(shí)。 它有 命令行接口 以及一個(gè) 可調(diào)用 方法。 它避免了許多測量時(shí)間的常見陷阱。 另見 Tim Peter 在 O’Reilly 出版的 Python Cookbook 第二版中“算法”章節(jié)的概述。
基本示例
以下示例顯示了如何使用 命令行接口 來比較三個(gè)不同的表達(dá)式:
$ Python3 -m timeit '"-".join(str(n) for n in range(100))'10000 loops, best of 5: 30.2 usec per loop$ python3 -m timeit '"-".join([str(n) for n in range(100)])'10000 loops, best of 5: 27.5 usec per loop$ python3 -m timeit '"-".join(map(str, range(100)))'10000 loops, best of 5: 23.2 usec per loop
這可以通過 Python 接口 實(shí)現(xiàn)
>>> 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 接口 還可以傳出一個(gè)可調(diào)用對(duì)象:
>>> timeit.timeit(lambda: "-".join(map(str, range(100))), number=10000)0.19665591977536678
但請(qǐng)注意 timeit() 僅在使用命令行界面時(shí)會(huì)自動(dòng)確定重復(fù)次數(shù)。 在 例子 一節(jié)你可以找到更多的進(jìn)階示例。
Python 接口
該模塊定義了三個(gè)便利函數(shù)和一個(gè)公共類:
timeit.timeit(stmt=’pass’, setup=’pass’, timer=
使用給定語句、 setup 代碼和 timer 函數(shù)創(chuàng)建一個(gè) Timer 實(shí)例,并執(zhí)行 number 次其 timeit() 方法??蛇x的 globals 參數(shù)指定用于執(zhí)行代碼的命名空間。
在 3.5 版更改: 添加可選參數(shù) globals 。
timeit.repeat(stmt=’pass’, setup=’pass’, timer=
使用給定語句、 setup 代碼和 timer 函數(shù)創(chuàng)建一個(gè) Timer 實(shí)例,并使用給定的 repeat 計(jì)數(shù)和 number 執(zhí)行運(yùn)行其 repeat() 方法??蛇x的 globals 參數(shù)指定用于執(zhí)行代碼的命名空間。
在 3.5 版更改: 添加可選參數(shù) globals 。
在 3.7 版更改: repeat 的默認(rèn)值由 3 更改為 5 。
timeit.default_timer()
默認(rèn)的計(jì)時(shí)器,總是 time.perf_counter() 。
在 3.3 版更改: time.perf_counter() 現(xiàn)在是默認(rèn)計(jì)時(shí)器。
class timeit.Timer(stmt=’pass’, setup=’pass’, timer=
用于小代碼片段的計(jì)數(shù)執(zhí)行速度的類。
構(gòu)造函數(shù)接受一個(gè)將計(jì)時(shí)的語句、一個(gè)用于設(shè)置的附加語句和一個(gè)定時(shí)器函數(shù)。兩個(gè)語句都默認(rèn)為 'pass' ;計(jì)時(shí)器函數(shù)與平臺(tái)有關(guān)(請(qǐng)參閱模塊文檔字符串)。 stmt 和 setup 也可能包含多個(gè)以 ; 或換行符分隔的語句,只要它們不包含多行字符串文字即可。該語句默認(rèn)在 timeit 的命名空間內(nèi)執(zhí)行;可以通過將命名空間傳遞給 globals 來控制此行為。
要測量第一個(gè)語句的執(zhí)行時(shí)間,請(qǐng)使用 timeit() 方法。 repeat() 和 autorange() 方法是方便的方法來調(diào)用 timeit() 多次。
setup 的執(zhí)行時(shí)間從總體計(jì)時(shí)執(zhí)行中排除。
stmt 和 setup 參數(shù)也可以使用不帶參數(shù)的可調(diào)用對(duì)象。這將在一個(gè)計(jì)時(shí)器函數(shù)中嵌入對(duì)它們的調(diào)用,然后由 timeit() 執(zhí)行。請(qǐng)注意,由于額外的函數(shù)調(diào)用,在這種情況下,計(jì)時(shí)開銷會(huì)略大一些。
在 3.5 版更改: 添加可選參數(shù) globals 。
-
timeit(number=1000000)
執(zhí)行 number 次主要語句。這將執(zhí)行一次 setup 語句,然后返回執(zhí)行主語句多次所需的時(shí)間,以秒為單位測量為浮點(diǎn)數(shù)。參數(shù)是通過循環(huán)的次數(shù),默認(rèn)為一百萬。要使用的主語句、 setup 語句和 timer 函數(shù)將傳遞給構(gòu)造函數(shù)。
備注
默認(rèn)情況下, timeit() 暫時(shí)關(guān)閉 garbage collection 。這種方法的優(yōu)點(diǎn)在于它使獨(dú)立時(shí)序更具可比性。缺點(diǎn)是GC可能是所測量功能性能的重要組成部分。如果是這樣,可以在 setup 字符串中的第一個(gè)語句重新啟用GC。例如:
timeit.Timer('for i in range(10): oct(i)', 'gc.enable()').timeit()
-
autorange(callback=None)
自動(dòng)決定調(diào)用多少次 timeit() 。
這是一個(gè)便利函數(shù),它反復(fù)調(diào)用 timeit() ,以便總時(shí)間 >= 0.2 秒,返回最終(循環(huán)次數(shù),循環(huán)所用的時(shí)間)。它調(diào)用 timeit() 的次數(shù)以序列 1, 2, 5, 10, 20, 50, … 遞增,直到所用的時(shí)間至少為0.2秒。
如果給出 callback 并且不是
None,則在每次試驗(yàn)后將使用兩個(gè)參數(shù)調(diào)用它:callback(number, time_taken)。3.6 新版功能.
-
repeat(repeat=5, number=1000000)
調(diào)用 timeit() 幾次。
這是一個(gè)方便的函數(shù),它反復(fù)調(diào)用 timeit() ,返回結(jié)果列表。第一個(gè)參數(shù)指定調(diào)用 timeit() 的次數(shù)。第二個(gè)參數(shù)指定 timeit() 的 number 參數(shù)。
備注
從結(jié)果向量計(jì)算并報(bào)告平均值和標(biāo)準(zhǔn)差這些是很誘人的。但是,這不是很有用。在典型情況下,最低值給出了機(jī)器運(yùn)行給定代碼段的速度的下限;結(jié)果向量中較高的值通常不是由Python的速度變化引起的,而是由于其他過程干擾你的計(jì)時(shí)準(zhǔn)確性。所以結(jié)果的 min() 可能是你應(yīng)該感興趣的唯一數(shù)字。之后,你應(yīng)該看看整個(gè)向量并應(yīng)用常識(shí)而不是統(tǒng)計(jì)。
在 3.7 版更改: repeat 的默認(rèn)值由 3 更改為 5 。
-
print_exc(file=None)
幫助程序從計(jì)時(shí)代碼中打印回溯。
典型使用:
t = Timer(...) # outside the try/excepttry:t.timeit(...) # or t.repeat(...)except Exception:t.print_exc()
與標(biāo)準(zhǔn)回溯相比,優(yōu)勢在于將顯示已編譯模板中的源行??蛇x的 file 參數(shù)指向發(fā)送回溯的位置;它默認(rèn)為 sys.stderr 。
命令行接口
從命令行調(diào)用程序時(shí),使用以下表單:
python -m timeit [-n N] [-r N] [-u U] [-s S] [-h] [statement ...]
如果了解以下選項(xiàng):
-n N, —number=N
執(zhí)行 ‘語句’ 多少次
-r N, —repeat=N
重復(fù)計(jì)時(shí)器的次數(shù)(默認(rèn)為5)
-s S, —setup=S
最初要執(zhí)行一次的語句(默認(rèn)為 pass )
-p, —process
測量進(jìn)程時(shí)間,而不是 wallclock 時(shí)間,使用 time.process_time() 而不是 time.perf_counter() ,這是默認(rèn)值
3.3 新版功能.
-u, —unit=U
specify a time unit for timer output; can select nsec, usec, msec, or sec
3.5 新版功能.
-v, —verbose
打印原始計(jì)時(shí)結(jié)果;重復(fù)更多位數(shù)精度
-h, —help
打印一條簡短的使用信息并退出
可以通過將每一行指定為單獨(dú)的語句參數(shù)來給出多行語句;通過在引號(hào)中包含參數(shù)并使用前導(dǎo)空格可以縮進(jìn)行。多個(gè) -s 選項(xiàng)的處理方式相似。
如果未給出 -n,則會(huì)通過嘗試按序列 1, 2, 5, 10, 20, 50, … 遞增的數(shù)值來計(jì)算合適的循環(huán)次數(shù),直到總計(jì)時(shí)間至少為 0.2 秒。
default_timer() 測量可能受到在同一臺(tái)機(jī)器上運(yùn)行的其他程序的影響,因此在需要精確計(jì)時(shí)時(shí)最好的做法是重復(fù)幾次計(jì)時(shí)并使用最佳時(shí)間。 -r 選項(xiàng)對(duì)此有利;在大多數(shù)情況下,默認(rèn)的 5 次重復(fù)可能就足夠了。 你可以使用 time.process_time() 來測量CPU時(shí)間。
備注
執(zhí)行 pass 語句會(huì)產(chǎn)生一定的基線開銷。這里的代碼不會(huì)試圖隱藏它,但你應(yīng)該知道它??梢酝ㄟ^不帶參數(shù)調(diào)用程序來測量基線開銷,并且Python版本之間可能會(huì)有所不同。
例子
可以提供一個(gè)在開頭只執(zhí)行一次的 setup 語句:
$ python -m timeit -s 'text = "sample string"; char = "g"' 'char in text'5000000 loops, best of 5: 0.0877 usec per loop$ python -m timeit -s 'text = "sample string"; char = "g"' 'text.find(char)'1000000 loops, best of 5: 0.342 usec per loop
在輸出信息中,共有三個(gè)字段。 首先是 loop count,它告訴你每個(gè)計(jì)時(shí)循環(huán)重復(fù)運(yùn)行了多少次語句體。 然后是 repetition count (‘best of 5’),它告訴你計(jì)時(shí)循環(huán)重復(fù)了多少次,最后是語句體在計(jì)時(shí)循環(huán)重復(fù)中最好的平均耗時(shí)。 即最快一次重復(fù)的耗時(shí)除以循環(huán)計(jì)數(shù)。
>>> import timeit>>> timeit.timeit('char in text', setup='text = "sample string"; char = "g"')0.41440500499993504>>> timeit.timeit('text.find(char)', setup='text = "sample string"; char = "g"')1.7246671520006203
使用 Timer 類及其方法可以完成同樣的操作:
>>> import timeit>>> t = timeit.Timer('char in text', setup='text = "sample string"; char = "g"')>>> t.timeit()0.3955516149999312>>> t.repeat()[0.40183617287970225, 0.37027556854118704, 0.38344867356679524, 0.3712595970846668, 0.37866875250654886]
以下示例顯示如何計(jì)算包含多行的表達(dá)式。 在這里我們對(duì)比使用 hasattr() 與 try/except 的開銷來測試缺失與提供對(duì)象屬性:
$ python -m timeit 'try:' ' str.__bool__' 'except AttributeError:' ' pass'20000 loops, best of 5: 15.7 usec per loop$ python -m timeit 'if hasattr(str, "__bool__"): pass'50000 loops, best of 5: 4.26 usec per loop$ python -m timeit 'try:' ' int.__bool__' 'except AttributeError:' ' pass'200000 loops, best of 5: 1.43 usec per loop$ python -m timeit 'if hasattr(int, "__bool__"): pass'100000 loops, best of 5: 2.23 usec per loop
>>> import timeit>>> # attribute is missing>>> s = """\... try:... str.__bool__... except AttributeError:... pass... """>>> timeit.timeit(stmt=s, number=100000)0.9138244460009446>>> s = "if hasattr(str, '__bool__'): pass">>> timeit.timeit(stmt=s, number=100000)0.5829014980008651>>>>>> # attribute is present>>> s = """\... try:... int.__bool__... except AttributeError:... pass... """>>> timeit.timeit(stmt=s, number=100000)0.04215312199994514>>> s = "if hasattr(int, '__bool__'): pass">>> timeit.timeit(stmt=s, number=100000)0.08588060699912603
要讓 timeit 模塊訪問你定義的函數(shù),你可以傳遞一個(gè)包含 import 語句的 setup 參數(shù):
def test():"""Stupid test function"""L = [i for i in range(100)]if __name__ == '__main__':import timeitprint(timeit.timeit("test()", setup="from __main__ import test"))
另一種選擇是將 globals() 傳遞給 globals 參數(shù),這將導(dǎo)致代碼在當(dāng)前的全局命名空間中執(zhí)行。這比單獨(dú)指定 import 更方便
def f(x):return x**2def g(x):return x**4def h(x):return x**8import timeitprint(timeit.timeit('[func(42) for func in (f,g,h)]', globals=globals()))
新聞標(biāo)題:創(chuàng)新互聯(lián)Python教程:timeit—-測量小代碼片段的執(zhí)行時(shí)間
鏈接URL:http://fisionsoft.com.cn/article/dpsighd.html


咨詢
建站咨詢
