在我看來,python社區(qū)分為了三個(gè)流派,分別是python 2.x組織,3.x組織和PyPy組織。這個(gè)分類基本上可以歸根于類庫的兼容性和速度。這篇文章將聚焦于一些通用代碼的優(yōu)化技巧以及編譯成C后性能的顯著提升,當(dāng)然我也會(huì)給出三大主要python流派運(yùn)行時(shí)間。我的目的不是為了證明一個(gè)比另一個(gè)強(qiáng),只是為了讓你知道如何在不同的環(huán)境下使用這些具體例子作比較。
使用生成器
一個(gè)普遍被忽略的內(nèi)存優(yōu)化是生成器的使用。生成器讓我們創(chuàng)建一個(gè)函數(shù)一次只返回一條記錄,而不是一次返回所有的記錄,如果你正在使用python2.x,這就是你為啥使用xrange替代range或者使用ifilter替代filter的原因。一個(gè)很好地例子就是創(chuàng)建一個(gè)很大的列表并將它們拼合在一起。
import timeitimport random def generate(num):while num:yield random.randrange(10)num -= 1 def create_list(num):numbers = []while num:numbers.append(random.randrange(10))num -= 1return numbersprint(timeit.timeit("sum(generate(999))", setup="from __main__ import generate", number=1000))>>> 0.88098192215 #Python 2.7>>> 1.416813850402832 #Python 3.2print(timeit.timeit("sum(create_list(999))", setup="from __main__ import create_list", number=1000))>>> 0.924163103104 #Python 2.7>>> 1.5026731491088867 #Python 3.2這不僅是快了一點(diǎn),也避免了你在內(nèi)存中存儲(chǔ)全部的列表!
Ctypes的介紹
對(duì)于關(guān)鍵性的性能代碼python本身也提供給我們一個(gè)API來調(diào)用C方法,主要通過 ctypes來實(shí)現(xiàn),你可以不寫任何C代碼來利用ctypes。默認(rèn)情況下python提供了預(yù)編譯的標(biāo)準(zhǔn)c庫,我們?cè)倩氐缴善鞯睦樱纯词褂胏types實(shí)現(xiàn)花費(fèi)多少時(shí)間。
import timeitfrom ctypes import cdll def generate_c(num):#Load standard C librarylibc = cdll.LoadLibrary("libc.so.6") #Linux#libc = cdll.msvcrt #Windowswhile num:yield libc.rand() % 10num -= 1 print(timeit.timeit("sum(generate_c(999))", setup="from __main__ import generate_c", number=1000))>>> 0.434374809265 #Python 2.7>>> 0.7084300518035889 #Python 3.2僅僅換成了c的隨機(jī)函數(shù),運(yùn)行時(shí)間減了大半!現(xiàn)在如果我告訴你我們還能做得更好,你信嗎?
Cython的介紹
Cython 是python的一個(gè)超集,允許我們調(diào)用C函數(shù)以及聲明變量來提高性能。嘗試使用之前我們需要先安裝Cython.
sudo pip install cython
Cython 本質(zhì)上是另一個(gè)不再開發(fā)的類似類庫Pyrex的分支,它將我們的類Python代碼編譯成C庫,我們可以在一個(gè)python文件中調(diào)用。對(duì)于你的python文件使用.pyx后綴替代.py后綴,讓我們看一下使用Cython如何來運(yùn)行我們的生成器代碼。
#cython_generator.pyximport random def generate(num):while num:yield random.randrange(10)num -= 1
新聞熱點(diǎn)
疑難解答
圖片精選