加快Python運行時速度的10種技巧
Python是一種腳本語言。 與C / C ++之類的編譯語言相比,Python在效率和性能上有一些缺點。 但是,我們可以使用一些技術來提高Python代碼的效率。 在本文中,我將向您展示我通常在工作中使用的加速技術。
測試環(huán)境是Python 3.7,macOS 10.14.6和2.3 GHz Intel Core i5。
0.優(yōu)化原理
在深入探討代碼優(yōu)化的細節(jié)之前,我們需要了解一些代碼優(yōu)化的基本原理。
- 確保代碼可以首先正常工作。 因為快速制作正確的程序要比制作快速的程序容易得多。
- 權衡優(yōu)化成本。 優(yōu)化要付出代價。 例如,更少的運行時通常需要更多的空間使用,或者更少的運行時通常需要更多的運行時間。
- 優(yōu)化不能犧牲代碼的可讀性。
1. Python中正確的數(shù)據(jù)類型用法
1.1用set替換list以檢查元素是否在序列中
根據(jù)Python的時間復雜度,list的s操作中x的平均情況為O(n)。 另一方面,集合的s操作中x的平均情況為O(1)。
1.2使用defaultdict初始化字典
我們應該使用defaultdict進行初始化。
2.用生成器表達式替換列表推導
- # Bad: 447ms
- nums_sum_list_comprehension = sum([num**2 for num in range(1000000)])
- # Good: 300
- msnums_sum_generator_expression = sum((num**2 for num in range(1000000)))
生成器表達式的另一個好處是,我們無需迭代就可以在不將整個列表對象構(gòu)建和保存在內(nèi)存中的情況下獲得結(jié)果。 換句話說,生成器表達式可以節(jié)省內(nèi)存使用量。
- import sys
- # Badnums_squared_list = [num**2 for num in range(1000000)]
- print(sys.getsizeof(nums_squared_list))
- # 87632
- # Goodnums_squared_generator = (num**2 for num in range(1000000))
- print(sys.getsizeof(nums_squared_generator))
- # 128
3.用局部變量替換全局變量
我們應該將全局變量放入函數(shù)中。 局部變量比全局變量快。
4.避免點操作
4.1避免函數(shù)訪問
每次我們使用。 要訪問該函數(shù),它將觸發(fā)特定的方法,例如__getattribute __()和__getattr __()。 這些方法將使用字典操作,這將導致時間成本。 我們可以使用從xx導入xx來消除此類費用。
根據(jù)技術3,我們還可以將全局函數(shù)分配給局部函數(shù)。
此外,我們可以將list.append()方法分配給本地函數(shù)。
4.2避免類屬性訪問
訪問self._value的速度比訪問局部變量的速度慢。 我們可以將class屬性分配給局部變量以加快運行時間。
5.避免不必要的抽象
當使用其他處理層(例如裝飾器,屬性訪問,描述符)包裝代碼時,這會使代碼變慢。 在大多數(shù)情況下,有必要重新考慮是否有必要使用這些層。 一些C / C ++程序員可能會遵循使用getter / setter函數(shù)訪問屬性的編碼風格。 但是我們可以使用更簡單的寫作風格。
6.避免數(shù)據(jù)重復
6.1避免無意義的數(shù)據(jù)復制
value_list是沒有意義的。
6.2更改值時避免使用temp變量
不需要臨時變量。
6.3連接字符串時用join()替換+
當使用a + b連接字符串時,Python將申請內(nèi)存空間,并將a和b分別復制到新應用的內(nèi)存空間。 這是因為Python中的字符串數(shù)據(jù)類型是不可變的對象。 如果串聯(lián)n個字符串,它將生成n-1個中間結(jié)果,并且每個中間結(jié)果都將應用于內(nèi)存空間并復制新的字符串。
另一方面,join()將節(jié)省時間。 它將首先計算需要應用的總內(nèi)存空間,然后一次申請所需的內(nèi)存,然后將每個字符串元素復制到內(nèi)存中。
7.利用if語句的短路評估
Python使用短路技術來加快對真值的評估。 如果第一個語句為假,則整個事情必須為假,因此它將返回該值。 否則,如果第一個值為true,則檢查第二個值并返回該值。
因此,為了節(jié)省運行時間,我們可以遵循以下規(guī)則:
- if a and b:變量a應該具有很高的False概率,因此Python不會計算b。
- if a or b:變量a應該具有較高的True概率,因此Python不會計算b。
8.循環(huán)優(yōu)化
8.1 for
for循環(huán)比while循環(huán)快。
8.2用隱式for循環(huán)替換顯式for循環(huán)
8.3減少內(nèi)部for循環(huán)的計算
我們將sqrt(x)從內(nèi)部for循環(huán)移動到外部for循環(huán)。
9.使用numba.jit
Numba可以將Python函數(shù)JIT編譯為機器代碼以執(zhí)行,從而大大提高了代碼速度。 有關numba的更多信息,請參見主頁。
我們使用上面的示例。
我們將sqrt(x)從內(nèi)部for循環(huán)移動到外部for循環(huán)。
10.使用cProfile查找時間成本函數(shù)
cProfile將輸出每個函數(shù)的時間使用情況。 因此我們可以找到時間成本函數(shù)。
通過分類視圖查看我在Medium上的其他帖子!GitHub:BrambleXuLinkedIn:Xu Liang博客:BrambleXu