一、前言
眾所周知,Python 不是一種執行效率較高的語言,此外在任何語言中,回圈都是一種非常消耗時間的操作,假如任意一種簡單的單步操作耗費的時間為 1 個單位,將此操作重復執行上萬次,最終耗費的時間也將增長上萬倍,

while 和 for 是 Python 中常用的兩種實作回圈的關鍵字,它們的運行效率實際上是有差距的,比如下面的測驗代碼:
Python學習交流Q群:906715085### 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 loop\t\t', timeit.timeit(while_loop, number=1)) print('for loop\t\t', timeit.timeit(for_loop, number=1)) if __name__ == '__main__': main() # => while loop 4.718853999860585 # => for loop 3.21157039981335
這是一個簡單的求和操作,計算從 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 loop\t\t', timeit.timeit(while_loop, number=1)) print('for loop\t\t', timeit.timeit(for_loop, number=1)) print('for loop with increment\t\t', timeit.timeit(for_loop_with_inc, number=1)) print('for loop with test\t\t', timeit.timeit(for_loop_with_test, number=1)) if __name__ == '__main__': main() # => while loop 4.718853999860585 # => for loop 3.211570399813354 # => for loop with increment 4.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 loop\t\t', timeit.timeit(while_loop, number=1)) print('for loop\t\t', timeit.timeit(for_loop, number=1)) print('sum range\t\t', timeit.timeit(sum_range, number=1)) if __name__ == '__main__': main() # => while loop 4.718853999860585 # => for loop 3.211570399813354 # => sum range 0.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 loop\t\t', timeit.timeit(while_loop, number=1)) print('for loop\t\t', timeit.timeit(for_loop, number=1)) print('sum range\t\t', timeit.timeit(sum_range, number=1)) print('math sum\t\t', timeit.timeit(math_sum, number=1)) if __name__ == '__main__': main() # => while loop 4.718853999860585 # => for loop 3.211570399813354 # => sum range 0.8658821999561042 # => math sum 2.400018274784088e-06
最終 math sum 的執行時間約為 2.4e-6,縮短了上百萬倍,這里的思路就是,既然回圈的效率低,一段代碼要重復執行上億次,
索性直接不要回圈,通過數學公式,把上億次的回圈操作變成只有一步操作,效率自然得到了空前的加強,
最后的結論(有點謎語人):
實作回圈的最快方式——就是不用回圈
對于 Python 而言,則盡可能地使用內置函式,將回圈中的純 Python 代碼降到最低,這一篇到這里就沒有了,這一篇分享的Python實作回圈最快的方式希望對你有用,記得點一個贊喲,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/453770.html
標籤:Python
