如果不首先想想這句Knuth的名言,就開始進(jìn)行優(yōu)化工作是不明智的。可是,你很快寫出來加入一些特性的代碼,可能會很丑陋,你需要注意了。這篇文章就是為這時候準(zhǔn)備的。
那么接下來就是一些很有用的工具和模式來快速優(yōu)化Python。它的主要目的很簡單:盡快發(fā)現(xiàn)瓶頸,修復(fù)它們并且確認(rèn)你修復(fù)了它們。
寫一個測試
在你開始優(yōu)化前,寫一個高級測試來證明原來代碼很慢。你可能需要采用一些最小值數(shù)據(jù)集來復(fù)現(xiàn)它足夠慢。通常一兩個顯示運(yùn)行時秒的程序就足夠處理一些改進(jìn)的地方了。
有一些基礎(chǔ)測試來保證你的優(yōu)化沒有改變原有代碼的行為也是很必要的。你也能夠在很多次運(yùn)行測試來優(yōu)化代碼的時候稍微修改這些測試的基準(zhǔn)。
那么現(xiàn)在,我們來來看看優(yōu)化工具把。
簡單的計(jì)時器
計(jì)時器很簡單,這是一個最靈活的記錄執(zhí)行時間的方法。你可以把它放到任何地方并且副作用很小。運(yùn)行你自己的計(jì)時器非常簡單,并且你可以將其定制,使它以你期望的方式工作。例如,你個簡單的計(jì)時器如下:
import time def timefunc(f): def f_timer(*args, **kwargs): start = time.time() result = f(*args, **kwargs) end = time.time() print f.__name__, 'took', end - start, 'time' return result return f_timer def get_number(): for x in xrange(5000000): yield x @timefuncdef expensive_function(): for x in get_number(): i = x ^ x ^ x return 'some result!' # prints "expensive_function took 0.72583088875 seconds"result = expensive_function()
當(dāng)然,你可以用上下文管理來讓它功能更加強(qiáng)大,添加一些檢查點(diǎn)或者一些其他的功能:
import time class timewith(): def __init__(self, name=''): self.name = name self.start = time.time() @property def elapsed(self): return time.time() - self.start def checkpoint(self, name=''): print '{timer} {checkpoint} took {elapsed} seconds'.format( timer=self.name, checkpoint=name, elapsed=self.elapsed, ).strip() def __enter__(self): return self def __exit__(self, type, value, traceback): self.checkpoint('finished') pass def get_number(): for x in xrange(5000000): yield x def expensive_function(): for x in get_number(): i = x ^ x ^ x return 'some result!' # prints something like:# fancy thing done with something took 0.582462072372 seconds# fancy thing done with something else took 1.75355315208 seconds# fancy thing finished took 1.7535982132 secondswith timewith('fancy thing') as timer: expensive_function() timer.checkpoint('done with something') expensive_function() expensive_function() timer.checkpoint('done with something else') # or directlytimer = timewith('fancy thing')expensive_function()timer.checkpoint('done with something')計(jì)時器還需要你做一些挖掘。包裝一些更高級的函數(shù),并且確定瓶頸在哪,然后深入的函數(shù)里,能夠不停的重現(xiàn)。當(dāng)你發(fā)現(xiàn)一些不合適的代碼,修復(fù)它,然后測試一遍以確認(rèn)它被修復(fù)了。
新聞熱點(diǎn)
疑難解答
圖片精選