2011-09-23 74 views
60

我這個使用timeit掙扎,並想知道如果任何人有,我想測試的速度任何提示如何在將變量傳遞給函數時使用python timeit?

基本上我有一個函數(即我傳遞一個值),並創造了這個:

if __name__=='__main__': 
    from timeit import Timer 
    t = Timer(superMegaIntenseFunction(10)) 
    print t.timeit(number=1) 

但是當我運行它,我得到奇怪的錯誤像timeit模塊來:

ValueError: stmt is neither a string nor callable 

如果我對自己的運行功能,它工作正常。它的時候,我包裝它的時候它模塊,我得到的錯誤(我試過使用雙引號,沒有..sameoutput)。

任何建議都會很棒!

謝謝!

回答

95

讓它可以調用的:

if __name__=='__main__': 
    from timeit import Timer 
    t = Timer(lambda: superMegaIntenseFunction(10)) 
    print t.timeit(number=1) 

應工作

+0

工作正常!非常感謝。我需要弄清楚什麼是lambda ..看起來像是有所作爲。謝謝Pablo – Lostsoul

+5

如果只有這個在文檔 – endolith

+13

哦,但lambda增加了一些開銷,所以不適合測試小的東西。 'timeit 5 * 5'爲33 ns,而'timeit(lambda:5 * 5)()'爲233 ns。 – endolith

16

你應該傳遞一個字符串。即

t = Timer('superMegaIntenseFunction(10)','from __main__ import superMegaIntenseFunction') 
+0

感謝您的回答oxtopus!它不起作用,當我把它包裝在引號中,所以它的字符串我得到這個錯誤:NameError:全球名稱'superMegaIntenseFunction'未定義。你認爲我還能嘗試什麼? – Lostsoul

+0

更正了包含設置參數的答案。 (http://docs.python。org/library/timeit.html#timeit.Timer) –

21

Timer(superMegaIntenseFunction(10))的意思是 「叫superMegaIntenseFunction(10),然後將結果傳遞給Timer」。這顯然不是你想要的。 Timer需要可調用(就像它聽起來:可以調用的東西,比如函數)或字符串(以便它可以將字符串的內容解釋爲Python代碼)。 Timer通過重複調用可調用事物並查看需要多少時間來工作。

Timer(superMegaIntenseFunction)會通過類型檢查,因爲superMegaIntenseFunction是可調用的。但Timer不知道要傳遞給superMegaIntenseFunction的值是多少。

解決這個問題的簡單方法當然是在代碼中使用字符串。我們需要傳遞一個'setup'參數給代碼,因爲在新的上下文中字符串被「解釋爲代碼」 - 它不能訪問相同的代碼,所以你需要運行另一個代碼來創建定義可用 - 請參閱@ oxtopus的答案。

使用lambda(如@Pablo的答案),我們可以將參數10綁定到調用superMegaIntenseFunction。我們正在做的所有事情是創建另一個函數,它不帶任何參數,並調用superMegaIntenseFunction10。就好像您使用def來創建另一個函數一樣,除了新函數沒有得到名稱(因爲它不需要)。

1

針對未來訪客的備註。如果你需要使它在pdb調試工作,superMegaIntenseFunction是不是在全球範圍內,你可以把它的工作,加入到globals

globals()['superMegaIntenseFunction'] = superMegaIntenseFunction 
timeit.timeit(lambda: superMegaIntenseFunction(x)) 

Note that the timing overhead is a little larger in this case because of the extra function calls. [source]