循環以外能作的事不要放在循環內,好比下面的優化能夠快一倍python
join
對於累加的方式,有大約5倍的提高算法
三、使用if is
數據結構
使用if is True
比if == True
將近快一倍app
x < y < z
x < y < z
效率略高,並且可讀性更好dom
**
而不是pow%timeit -n 10000 c = pow(2,20) %timeit -n 10000 c = 2**20 10000 loops, best of 3: 284 ns per loop 10000 loops, best of 3: 16.9 ns per loop
**
就是快10倍以上!函數
對於and,應該把知足條件少的放在前面,對於or,把知足條件多的放在前面oop
a = range(2000)
%timeit -n 100 [i for i in a if 10 < i < 20 or 1000 < i < 2000]
%timeit -n 100 [i for i in a if 1000 < i < 2000 or 100 < i < 20]
%timeit -n 100 [i for i in a if i % 2 == 0 and i > 1900]
%timeit -n 100 [i for i in a if i > 1900 and i % 2 == 0]
100 loops, best of 3: 287 µs per loop
100 loops, best of 3: 214 µs per loop
100 loops, best of 3: 128 µs per loop
100 loops, best of 3: 56.1 µs per loop
python dict和set都是使用hash表來實現,查找元素的時間複雜度是O(1)性能
對於dict和list等數據結構的對象,直接賦值使用的是引用的方式。而有些狀況下須要複製整個對象,這時可使用copy包裏的copy和deepcopy,測試
這兩個函數的不一樣之處在於後者是遞歸複製的。效率也不同:(如下程序在ipython中運行)大數據
import copy a = range(100000) %timeit -n 10 copy.copy(a) # 運行10次 copy.copy(a) %timeit -n 10 copy.deepcopy(a) 10 loops, best of 3: 1.55 ms per loop 10 loops, best of 3: 151 ms per loop
表解析要比在循環中從新構建一個新的 list 更爲高效,所以咱們能夠利用這一特性來提升運行的效率。
1 from time import time 2 t = time() 3 list = ['a','b','is','python','jason','hello','hill','with','phone','test', 4 'dfdf','apple','pddf','ind','basic','none','baecr','var','bana','dd','wrd'] 5 total=[] 6 for i in range (1000000): 7 for w in list: 8 total.append(w) 9 print "total run time:" 10 print time()-t
使用列表解析:
上述代碼直接運行大概須要 17s,而改成使用列表解析後 ,運行時間縮短爲 9.29s。將近提升了一半。生成器表達式則是在 2.4 中引入的新內容,語法和列表解析相似,可是在大數據量處理時,生成器表達式的優點較爲明顯,它並不建立一個列表,只是返回一個生成器,所以效率較高。在上述例子上中代碼 a = [w for w in list] 修改成 a = (w for w in list),運行時間進一步減小,縮短約爲 2.98s。
在循環的時候使用 xrange 而不是 range;使用 xrange 能夠節省大量的系統內存,由於 xrange() 在序列中每次調用只產生一個整數元素。而 range() 將直接返回完整的元素列表,用於循環時會有沒必要要的開銷。在 python3 中 xrange 再也不存在,裏面 range 提供一個能夠遍歷任意長度的範圍的 iterator。
使用局部變量,避免」global」 關鍵字。python 訪問局部變量會比全局變量要快得多,因 此能夠利用這一特性提高性能
if done is not None 比語句 if done != None 更快
不少Python優化的文章,都會談及這個。那麼,到底能提升多少呢?咱們來試試看
1 import random 2 import time 3 4 start_time = time.time() 5 print start_time 6 7 j = 1 8 while True: 9 j += 1 10 end_time = time.time() 11 if end_time - start_time >= 1 : 12 break 13 print j 14 print end_time 15 16 print "======== split ==========" 17 start_time = time.time() 18 print start_time 19 20 j = 1 21 while 1: 22 j += 1 23 end_time = time.time() 24 if end_time - start_time >= 1 : 25 break 26 print j 27 print end_time
輸出結果:
1399342863.16
2573550
1399342864.16
======== split ==========
1399342864.18
2973070
1399342865.18
一個是25萬,一個是29萬。大約提高了16%左右的性能。其實不是很明顯。只是聊勝於無。
1五、若是須要交換兩個變量的值使用 a,b=b,a 而不是藉助中間變量 t=a;a=b;b=t;
用range()函數生成序列,與自定義序列
(1)a = range(0,6)
(2)a = [0, 1, 2, 3, 4, 5]
分別測試了一下,結果以下:
loop_num: 1029877
loop_num: 1602341
結論:仍是本身顯式定義序列,效率更高。
生成一個序列的副本:用copy,與用切片特性
a = [0, 1, 2, 3, 4, 5]
(1)b = copy.copy(a)
(2)b = a[:]
分別測試了一下,結果以下:
loop_num: 677838
loop_num: 1530012
結論:變通的切片應用做爲拷貝,比淺拷貝函數效率更高。注意,深拷貝效率很低!
1八、慎用python內置函數
python內置函數,只是爲了應對通用狀況。在不少狀況下,內置函數的性能,遠遠不如本身寫的,有針對性的函數。動動手,換個算法,就能把性能提升一倍以上。
s1, s2 = 'ax', 'bx' %timeit -n 100000 'abc%s%s' % (s1, s2) %timeit -n 100000 'abc{0}{1}'.format(s1, s2) %timeit -n 100000 'abc' + s1 + s2 100000 loops, best of 3: 183 ns per loop 100000 loops, best of 3: 169 ns per loop 100000 loops, best of 3: 103 ns per loop
三種狀況中,%的方式是最慢的,可是三者的差距並不大(都很是快)。(我的以爲%的可讀性最好)
用del能夠將對象佔用內存空間的引用計數值置零(Deletion of a name removes the binding of that name from the local or global namespace)。它並不能讓對象佔用的內存被回收,但一段內存的引用計數變爲零,就說明它能夠再次被從新使用了(因此del後,沒必要要GC介入)。
若是不用del,下面這段代碼就可能MemoryError
1 import numpy as np 2 3 matrix1 = np.zeros((60000,100000)) 4 matrix2 = np.zeros((60000,100000)) 5 # using matrix1 6 # using matrix2
利用del,能夠將用完後不必佔用內存的對象刪掉,下面的代碼對內存耗費就沒上面的大。
1 import numpy as np 2 3 matrix1 = np.zeros((60000,100000)) 4 # using matrix1 5 del matrix1 6 7 matrix2 = np.zeros((60000,100000)) 8 # using matrix2 9 del matrix2