Python 哪一種方式循環最快,或許顛覆你的認知!

王林
發布: 2023-04-17 23:10:01
轉載
1231 人瀏覽過

</p>眾所周知,Python 不是一種執行效率較高的語言。此外在任何語言中,循環都是一種非常消耗時間的操作。假如任一簡單的單步操作耗費的時間為 1 個單位,將此操作重複執行上萬次,最終耗費的時間也將增長上萬倍。

while 和 for 是 Python 中常用的兩種實作循環的關鍵字,它們的運作效率其實是有差距的。例如下面的測試程式碼:

import timeit
def while_loop(n=100_000_000):
 i = 0
 s = 0
 while i < n:
 s = i
 i = 1
 return s
def for_loop(n=100_000_000):
 s = 0
 for i in range(n):
 s = i
 return s
def main():
 print('while looptt', timeit.timeit(while_loop, number=1))
 print('for looptt', timeit.timeit(for_loop, number=1))
if __name__ == '__main__':
 main()
# => while loop 4.718853999860585
# => for loop 3.211570399813354

這是一個簡單的求和操作,計算從 1 到 n 之間所有自然數的總和。可以看到 for 迴圈相比 while 快 1.5 秒。

其中的差距主要在於兩者的機制不同。

在每次循環中,while 實際上比 for 多執行了兩步驟操作:邊界檢查和變數 i 的自增。即每進行一次循環,while 都會做一次邊界檢查 (while i < n)和自增計算(i =1)。這兩步驟操作都是顯式的純 Python 程式碼。

for 迴圈不需要執行邊界檢查和自增操作,沒有增加明確的 Python 程式碼(純 Python 程式碼效率低於底層的 C 程式碼)。當循環的次數夠多,就出現了明顯的效率差距。

可以再增加兩個函數,在for 循環中加上不必要的邊界檢查和自增計算:

import timeit
def while_loop(n=100_000_000):
 i = 0
 s = 0
 while i < n:
 s = i
 i = 1
 return s
def for_loop(n=100_000_000):
 s = 0
 for i in range(n):
 s = i
 return s
def for_loop_with_inc(n=100_000_000):
 s = 0
 for i in range(n):
 s = i
 i = 1
 return s
def for_loop_with_test(n=100_000_000):
 s = 0
 for i in range(n):
 if i < n:
 pass
 s = i
 return s
def main():
 print('while looptt', timeit.timeit(while_loop, number=1))
 print('for looptt', timeit.timeit(for_loop, number=1))
 print('for loop with incrementtt',
 timeit.timeit(for_loop_with_inc, number=1))
 print('for loop with testtt', timeit.timeit(for_loop_with_test, number=1))
if __name__ == '__main__':
 main()
# => while loop 4.718853999860585
# => for loop 3.211570399813354
# => for loop with increment4.602369500091299
# => for loop with test 4.18337869993411

可以看出,增加的邊界檢查和自增操作確實大大影響了 for 迴圈的執行效率。

前面提到過,Python 底層的解釋器和內建函數是用 C 語言實現的。而 C 語言的執行效率遠大於 Python。

對於上面的求等差數列總和的操作,借助於 Python 內建的 sum 函數,可以獲得遠大於 for 或 while 迴圈的執行效率。

import timeit
def while_loop(n=100_000_000):
 i = 0
 s = 0
 while i < n:
 s = i
 i = 1
 return s
def for_loop(n=100_000_000):
 s = 0
 for i in range(n):
 s = i
 return s
def sum_range(n=100_000_000):
 return sum(range(n))
def main():
 print('while looptt', timeit.timeit(while_loop, number=1))
 print('for looptt', timeit.timeit(for_loop, number=1))
 print('sum rangett', timeit.timeit(sum_range, number=1))
if __name__ == '__main__':
 main()
# => while loop 4.718853999860585
# => for loop 3.211570399813354
# => sum range0.8658821999561042

可以看到,使用內建函數 sum 替代循環之後,程式碼的執行效率實現了成倍的成長。

內建函數sum 的累加操作其實也是一種循環,但它由C 語言實現,而for 循環中的求和操作是由純Python 程式碼s = i實現的。 C > Python。

再拓展一下思考。小時候都聽過童年高斯巧妙地計算 1 到 100 總和的故事。1…100 總和等於 (1 100) * 50。這個計算方法同樣可以應用在上面的求和操作。

import timeit
def while_loop(n=100_000_000):
 i = 0
 s = 0
 while i < n:
 s = i
 i = 1
 return s
def for_loop(n=100_000_000):
 s = 0
 for i in range(n):
 s = i
 return s
def sum_range(n=100_000_000):
 return sum(range(n))
def math_sum(n=100_000_000):
 return (n * (n - 1)) // 2
def main():
 print('while looptt', timeit.timeit(while_loop, number=1))
 print('for looptt', timeit.timeit(for_loop, number=1))
 print('sum rangett', timeit.timeit(sum_range, number=1))
 print('math sumtt', timeit.timeit(math_sum, number=1))
if __name__ == '__main__':
 main()
# => while loop 4.718853999860585
# => for loop 3.211570399813354
# => sum range0.8658821999561042
# => math sum 2.400018274784088e-06

最終 math sum 的執行時間約為 2.4e-6,縮短了上百萬倍。這裡的想法就是,既然循環的效率低,一段程式碼要重複執行上億次。

索性直接不要循環,透過數學公式,把上億次的循環操作變成只有一步操作。效率自然得到了空前的加強。

最後的結論(有點謎語人):

實現循環的最快方式— — — ——就是不用循環

對於Python 而言,則盡可能地使用內建函數,將循環中的純Python 程式碼降到最低。

以上是Python 哪一種方式循環最快,或許顛覆你的認知!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:51cto.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!