Python成為編程語言中的第一!送你20條Python性能優化的建議!
1、優化算法時間復雜度
算法的時間復雜度對程序的執行效率影響最大,在Python中可以通過選擇合適的數據結構來優化時間復雜度,如list和set查找某一個元素的時間復雜度分別是O(n)和O(1)。不同的場景有不同的優化方式,總得來說,一般有分治,分支界限,貪心,動態規劃等思想。
timeit後面的-n表示運行的次數,後兩行對應的是兩個timeit的輸出,下同。由此可見後者慢一個數量級。
進群:548377875 即可獲取數十套PDF哦!
但是對於需要循環遍歷的情況:
對於內存不是非常大的list,可以直接返回一個list,但是可讀性yield更佳(人個喜好)。
python2.x內置generator功能的有xrange函數、itertools包等。
6、優化循環
循環之外能做的事不要放在循環內,比如下面的優化可以快一倍:
8、使用join合並叠代器中的字符串
join對於累加的方式,有大約5倍的提升。
9、選擇合適的格式化字符方式
10、不借助中間變量交換兩個變量的值
12、使用級聯比較x < y < z
13、while 1 比 while True 更快
14、使用**而不是pow
17、使用C擴展(Extension)
目前主要有CPython(python最常見的實現的方式)原生API, ctypes,Cython,cffi三種方式,它們的作用是使得Python程序可以調用由C編譯成的動態鏈接庫,其特點分別是:
CPython原生API: 通過引入Python.h頭文件,對應的C程序中可以直接使用Python的數據結構。實現過程相對繁瑣,但是有比較大的適用範圍。
ctypes: 通常用於封裝(wrap)C程序,讓純Python程序調用動態鏈接庫(Windows中的dll或Unix中的so文件)中的函數。如果想要在python中使用已經有C類庫,使用ctypes是很好的選擇,有一些基準測試下,python2+ctypes是性能最好的方式。
Cython: Cython是CPython的超集,用於簡化編寫C擴展的過程。Cython的優點是語法簡潔,可以很好地兼容numpy等包含大量C擴展的庫。Cython的使得場景一般是針對項目中某個算法或過程的優化。在某些測試中,可以有幾百倍的性能提升。
cffi: cffi的就是ctypes在pypy(詳見下文)中的實現,同進也兼容CPython。cffi提供了在python使用C類庫的方式,可以直接在python代碼中編寫C代碼,同時支持鏈接到已有的C類庫。
使用這些優化方式一般是針對已有項目性能瓶頸模塊的優化,可以在少量改動原有項目的情況下大幅度地提高整個程序的運行效率。
18、並行編程
因為GIL的存在,Python很難充分利用多核CPU的優勢。但是,可以通過內置的模塊multiprocessing實現下面幾種並行模式:
多進程:對於CPU密集型的程序,可以使用multiprocessing的Process,Pool等封裝好的類,通過多進程的方式實現並行計算。但是因為進程中的通信成本比較大,對於進程之間需要大量數據交互的程序效率未必有大的提高。
多線程:對於IO密集型的程序,multiprocessing.dummy模塊使用multiprocessing的接口封裝threading,使得多線程編程也變得非常輕松(比如可以使用Pool的map接口,簡潔高效)。
分布式:multiprocessing中的Managers類提供了可以在不同進程之共享數據的方式,可以在此基礎上開發出分布式的程序。
不同的業務場景可以選擇其中的一種或幾種的組合實現程序性能的優化。
19、終級大殺器:PyPy
PyPy是用RPython(CPython的子集)實現的Python,根據官網的基準測試數據,它比CPython實現的Python要快6倍以上。快的原因是使用了Just-in-Time(JIT)編譯器,即動態編譯器,與靜態編譯器(如gcc,javac等)不同,它是利用程序運行的過程的數據進行優化。由於歷史原因,目前pypy中還保留著GIL,不過正在進行的STM項目試圖將PyPy變成沒有GIL的Python。
如果python程序中含有C擴展(非cffi的方式),JIT的優化效果會大打折扣,甚至比CPython慢(比Numpy)。所以在PyPy中最好用純Python或使用cffi擴展。
隨著STM,Numpy等項目的完善,相信PyPy將會替代CPython。
20、使用性能分析工具
除了上面在ipython使用到的timeit模塊,還有cProfile。cProfile的使用方式也非常簡單: python -m cProfile filename.py,filename.py 是要運行程序的文件名,可以在標準輸出中看到每一個函數被調用的次數和運行的時間,從而找到程序的性能瓶頸,然後可以有針對性地優化。
Python成為編程語言中的第一!送你20條Python性能優化的建議!