Python是一個很酷的語言,因為你可以在很短的時間內(nèi)利用很少的代碼做很多事情。不僅如此,它還能輕松地支持多任務(wù),比如多進程等。Python批評者有時會說Python執(zhí)行緩慢。本文將嘗試介紹6個技巧,可加速你的Python應(yīng)用程序。
1.讓關(guān)鍵代碼依賴于外部包
雖然Python讓許多編程任務(wù)變得容易,但它可能并不總能為緊急的任務(wù)提供最佳性能。你可以為緊急的任務(wù)使用C、C++或機器語言編寫的外部包,這樣可以提高應(yīng)用程序的性能。這些包都是不能跨平臺的,這意味著你需要根據(jù)你正在使用的平臺,尋找合適的包。簡而言之,這個方案放棄了一些應(yīng)用程序的可移植性,以換取只有在特定主機上直接編程才能獲得的程序性能。這里有一些你應(yīng)該考慮加入到你的“性能兵工廠”的包:
這些包以不同的方式提高性能。例如,Pyrex能夠擴展Python所能做的事情,例如使用C的數(shù)據(jù)類型來讓內(nèi)存任務(wù)更加有效或直接。PyInIne讓你在Python應(yīng)用程序中直接使用C代碼。程序中的內(nèi)聯(lián)代碼單獨編譯,但它在利用C語言所能提供的效率的同時,也讓所有的代碼都在同一個地方。
2.排序時使用鍵(key)
有很多老的Python排序代碼,它們在你創(chuàng)建一個自定義的排序時花費你的時間,但在運行時確實能加速執(zhí)行排序過程。元素排序的最好方法是盡可能使用鍵(key)和默認的sort()排序方法。例如,考慮下面的代碼:
1
2
3
4
5
6
7
8
9
10
11
|
import operator somelist = [( 1 , 5 , 8 ), ( 6 , 2 , 4 ), ( 9 , 7 , 5 )] somelist.sort(key = operator.itemgetter( 0 )) somelist #Output = [(1, 5, 8), (6, 2, 4), (9, 7, 5)] somelist.sort(key = operator.itemgetter( 1 )) somelist #Output = [(6, 2, 4), (1, 5, 8), (9, 7, 5)] somelist.sort(key = operator.itemgetter( 2 )) somelist #Output = [(6, 2, 4), (9, 7, 5), (1, 5, 8)], |
每一個實例中,根據(jù)你選擇的作為key參數(shù)部分的索引,數(shù)組進行了排序。類似于利用數(shù)字進行排序,這種方法同樣適用于利用字符串排序。
3.優(yōu)化循環(huán)
每種編程語言都會強調(diào)需要優(yōu)化循環(huán)。當使用Python的時候,你可以依靠大量的技巧使得循環(huán)運行得更快。然而,開發(fā)者經(jīng)常漏掉的一個方法是:避免在一個循環(huán)中使用點操作。例如,考慮下面的代碼:
1
2
3
4
5
6
7
8
|
lowerlist = [ 'this' , 'is' , 'lowercase' ] upper = str .upper upperlist = [] append = upperlist.append for word in lowerlist: append(upper(word)) print (upperlist) #Output = ['THIS', 'IS', 'LOWERCASE'] |
每一次你調(diào)用方法str.upper,Python都會求該方法的值。然而,如果你用一個變量代替求得的值,值就變成了已知的,Python就可以更快地執(zhí)行任務(wù)。優(yōu)化循環(huán)的關(guān)鍵,是要減少Python在循環(huán)內(nèi)部執(zhí)行的工作量,因為Python原生的解釋器在那種情況下,真的會減緩執(zhí)行的速度。
(注意:優(yōu)化循環(huán)的方法有很多,這只是其中的一個。例如,許多程序員都會說,列表推導是在循環(huán)中提高執(zhí)行速度的最好方式。這里的關(guān)鍵是,優(yōu)化循環(huán)是程序取得更高的執(zhí)行速度的更好方式之一。)
4.使用較新版本的Python
在網(wǎng)上搜索Python信息,都會發(fā)現(xiàn)無數(shù)人在問,從Python一個版本遷移到另一個版本的問題的信息。一般來說,Python的每一個版本都包含了能讓其比上個版本運行更快的優(yōu)化。版本遷移的限制因素是,你喜歡的那些庫是否已經(jīng)遷移到Python的較新版本。相比于詢問是否應(yīng)該進行版本遷移,關(guān)鍵問題是確定一個新版本什么時候有足夠的支持,以保證遷移的可行性。
你需要驗證你的代碼仍然運行。你需要在Python的新版本下使用你獲得的新庫,然后檢查你的應(yīng)用程序是否需要重大改變。只有在你作出必要的更正之后,你才會注意到版本之間的差別。然而,如果你正好確保你的應(yīng)用程序能在新版本下運行,而不需要任何改變,你可能會錯過那些版本升級帶來的新特性。一旦你進行了遷移,你應(yīng)該為你的新版本下的應(yīng)用程序?qū)懸粋€說明,檢查有問題的地方,并且優(yōu)先考慮利用新版本的特性去更新那些地方。這樣用戶將會在升級的過程中更早的看到一個更大的性能提升。
5.嘗試多種編碼方法
如果每次你創(chuàng)建一個應(yīng)用程序都是用相同的編碼方法,幾乎肯定會導致一些你的應(yīng)用程序比它能夠達到的運行效率慢的情況。作為分析過程的一部分,你可以嘗試一些實驗。例如,在一個字典中管理一些元素,你可以采用安全的方法確定元素是否已經(jīng)存在并更新,或者你可以直接添加元素,然后作為異常處理該元素不存在情況。考慮第一個編碼的例子:
1
2
3
4
5
6
7
8
|
n = 16 myDict = {} for i in range ( 0 , n): char = 'abcd' [i % 4 ] if char not in myDict: myDict[char] = 0 myDict[char] + = 1 print (myDict) |
這段代碼通常會在myDict開始為空時運行得更快。然而,當mydict通常被數(shù)據(jù)填充(或者至少大部分被充填)時,另一種方法效果更好。
1
2
3
4
5
6
7
8
9
|
n = 16 myDict = {} for i in range ( 0 , n): char = 'abcd' [i % 4 ] try : myDict[char] + = 1 except KeyError: myDict[char] = 1 print (myDict) |
兩種情況下具有相同的輸出:{‘d': 4, ‘c': 4, ‘b': 4, ‘a': 4}。唯一的不同是這個輸出是如何得到的。跳出固定的思維模式,創(chuàng)造新的編碼技巧,能夠幫助你利用你的應(yīng)用程序獲得更快的結(jié)果。
6.交叉編譯應(yīng)用程序
開發(fā)者有時會忘記,電腦實際上是不懂任何用于創(chuàng)建現(xiàn)代應(yīng)用程序的語言,電腦所能懂得是機器代碼。為了能在電腦上運行應(yīng)用程序,你使用一個應(yīng)用將人類可讀的代碼你轉(zhuǎn)換成計算機能理解的。有時候用一種語言,比如Python,寫一個應(yīng)用,并用另一種語言,比如C++,運行它,從性能的角度來看是有意義的。這取決于你想要應(yīng)用程序去做什么,以及主機系統(tǒng)可以提供的資源。
一個有趣的交叉編譯器,Nuitka,可以將你的Python代碼轉(zhuǎn)換為C++代碼。這么做的結(jié)果是,你可以在原生模式下執(zhí)行應(yīng)用程序,而不是依靠解釋器。根據(jù)平臺和任務(wù),你可以看到一個顯著的性能提升。
(注意:Nuitka目前還處于測試階段,所以用它來產(chǎn)品程序時需要小心。實際上,目前最好將其用于實驗。現(xiàn)在也有一些關(guān)于交叉編譯是否是得到更好性能的最佳方式的討論。開發(fā)者已經(jīng)利用交叉編譯好幾年了,目的是實現(xiàn)特定的目標,比如更好的應(yīng)用程序的速度。記住,每一個解決方案都會有得有失,你應(yīng)該在將一個解決方案用于生產(chǎn)環(huán)境之前就好好考慮一下得失情況。)
在使用一個交叉編譯器時,要確保它支持你使用的Python的版本。Nuitka支持Python2.6、2.7、3.2和3.3。想讓這個方案發(fā)揮作用,你需要一個Python解釋器和一個C++編譯器。Nuitka支持多種C++編譯器,包括Microsoft Visual Studio、MinGW 和 Clang/LLVM。
交叉編譯也可能帶來一些嚴重的負面影響。例如,當利用Nuitka工作時,你會發(fā)現(xiàn)即使一個小程序也能消耗很大的硬盤空間,這是因為Nuitka使用大量的動態(tài)鏈接庫(DLLs)實現(xiàn)Python的功能。所以當你面對一個資源有限的系統(tǒng)時,這個方案可能不會很好的起作用。
總結(jié)
這六個技巧中的任意一個,都可以幫助你創(chuàng)造更快的Python程序。但任何技巧都不是萬能的,不能每次都起作用。有些技巧在Python的特定版本下比其他技巧的更有效——甚至系統(tǒng)平臺也能影響它們的效果。你需要配置你的應(yīng)用,確定哪個地方讓其運行緩慢,然后嘗試似乎能最好的解決這些問題的一些技巧。