選擇了腳本語言就要忍受其速度,這句話在某種程度上說明了 python 作為腳本的一個不足之處,那就是執行效率和性能不夠理想,特別是在 performance 較差的機器上,因此有必要進行一定的代碼優化來提高程序的執行效率。如何進行 Python 性能優化,是本文探討的主要問題。本文會涉及常見的代碼優化方法,性能優化工具的使用以及如何診斷代碼的性能瓶頸等內容,希望可以給 Python 開發人員一定的參考。
Python 代碼優化常見技巧
代碼優化能夠讓程序運行更快,它是在不改變程序運行結果的情況下使得程序的運行效率更高,根據 80/20 原則,實現程序的重構、優化、擴展以及文檔相關的事情通常需要消耗 80% 的工作量。優化通常包含兩方面的內容:減小代碼的體積,提高代碼的運行效率。
改進演算法,選擇合適的數據結構
一個良好的演算法能夠對性能起到關鍵作用,因此性能改進的首要點是對演算法的改進。在演算法的時間複雜度排序上依次是:
O(1) -> O(lg n) -> O(n lg n) -> O(n^2) -> O(n^3) -> O(n^k) -> O(k^n) -> O(n!)
因此如果能夠在時間複雜度上對演算法進行一定的改進,對性能的提高不言而喻。但對具體演算法的改進不屬於本文討論的範圍,讀者可以自行參考這方面資料。下面的內容將集中討論數據結構的選擇。
- 字典 (dictionary) 與列表 (list)
Python 字典中使用了 hash table,因此查找操作的複雜度為 O(1),而 list 實際是個數組,在 list 中,查找需要遍歷整個 list,其複雜度為 O(n),因此對成員的查找訪問等操作字典要比 list 更快。
清單 1. 代碼 dict.py 03 | list = [ 'a' , 'b' , 'is' , 'python' , 'jason' , 'hello' , 'hill' , 'with' , 'phone' , 'test' , |
04 | 'dfdf' , 'apple' , 'pddf' , 'ind' , 'basic' , 'none' , 'baecr' , 'var' , 'bana' , 'dd' , 'wrd' ] |
08 | for i in range ( 1000000 ): |
09 | for find in [ 'is' , 'hat' , 'new' , 'list' , 'old' , '.' ]: |
12 | print "total run time:" |
上述代碼運行大概需要 16.09seconds。如果去掉行 #list = dict.fromkeys(list,True) 的註釋,將 list 轉換為字典之後再運行,時間大約為 8.375 seconds,效率大概提高了一半。因此在需要多數據成員進行頻繁的查找或者訪問的時候,使用 dict 而不是 list 是一個較好的選擇。
set 的 union, intersection,difference 操作要比 list 的迭代要快。因此如果涉及到求 list 交集,並集或者差的問題可以轉換為 set 來操作。
清單 2. 求 list 的交集: 03 | lista = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 13 , 34 , 53 , 42 , 44 ] |
06 | for i in range ( 1000000 ): |
10 | intersection.append(a) |
13 | print "total run time:" |
上述程序的運行時間大概為:
total run time:
38.4070000648
清單 3. 使用 set 求交集 3 | lista = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 13 , 34 , 53 , 42 , 44 ] |
6 | for i in range ( 1000000 ): |
7 | list ( set (lista)& set (listb)) |
8 | print "total run time:" |
改為 set 后程序的運行時間縮減為 8.75,提高了 4 倍多,運行時間大大縮短。讀者可以自行使用表 1 其他的操作進行測試。
表 1. set 常見用法 語法 | 操作 | 說明 |
set(list1) | set(list2) | union | 包含 list1 和 list2 所有數據的新集合 |
set(list1) & set(list2) | intersection | 包含 list1 和 list2 中共同元素的新集合 |
set(list1) - set(list2) | difference | 在 list1 中出現但不在 list2 中出現的元素的集合 |
對循環的優化
對循環的優化所遵循的原則是盡量減少循環過程中的計算量,有多重循環的盡量將內層的計算提到上一層。 下面通過實例來對比循環優化后所帶來的性能的提高。程序清單 4 中,如果不進行循環優化,其大概的運行時間約為 132.375。
清單 4. 為進行循環優化前 03 | lista = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ] |
04 | listb = [ 0.1 , 0.2 , 0.3 , 0.4 , 0.5 , 0.6 , 0.7 , 0.8 , 0.9 , 0.01 ] |
05 | for i in range ( 1000000 ): |
06 | for a in range ( len (lista)): |
07 | for b in range ( len (listb)): |
09 | print "total run time:" |
現在進行如下優化,將長度計算提到循環外,range 用 xrange 代替,同時將第三層的計算 lista[a] 提到循環的第二層。
清單 5. 循環優化后 ------分隔線----------------------------
- 上一篇:EasyMock教程--入門指南
- 下一篇:安裝 Mate 1.4在Ubuntu 12.04等系統中
- 文章分類
-
新聞動態 企鵝看世界 軟體更新資訊 新手入門 資料庫類 系統安全 系統管理 網路管理 使用經驗 編程開發 企業應用 硬體相關 Unix家族 觀點評論 人物介紹 技術前沿 專題 開源生活 開源美圖 英文資料 Eden團隊出品 開源軟體庫
- 軟體導航
-
- 發行版類 內核相關 伺服器類 模擬模擬 文件管理
- 系統安全 多媒體類 硬體工具 編程開發 網路熱門
- 雜類工具 網路工具 圖形圖像 閱讀編輯 書籍資料
- 遊戲軟體 辦公軟體 數據備份 中文相關 系統管理
- 科學計算 資料庫類 XWin系統
- 論壇導航
-
- 初級應用-> 新手入門 | 伺服器應用 | 中文化 | 軟體使用交流 | 硬體驅動 | 圖片秀 | 茶館
- 高級應用->資料庫 | 系統安全 | 嵌入式應用|
- 編程開發-> C/C++(STL/boost) | 內核 | RAD|Perl/PHP/Python | JAVA/XML | Shell
- 發行版-> Redhat和Fedora | Debian | Gentoo | Slackware/Suse | Mandrake/Mandriva
- Unix ->FreeBSD | Solaris | 其他Unix討論