Python?實現(xiàn)循環(huán)最快方式(for、while?等速度對比)
文章轉(zhuǎn)自微信公眾號-Python之禪
眾所周知,Python
不是一種執(zhí)行效率較高的語言。此外在任何語言中,循環(huán)都是一種非常消耗時間的操作。假如任意一種簡單的單步操作耗費的時間為 1 個單位,將此操作重復(fù)執(zhí)行上萬次,最終耗費的時間也將增長上萬倍。
while
和 for
是 Python
中常用的兩種實現(xiàn)循環(huán)的關(guān)鍵字,它們的運行效率實際上是有差距的。
比如下面的測試代碼:
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.211570399813354
這是一個簡單的求和操作,計算從 1 到 n 之間所有自然數(shù)的總和??梢钥吹?for
循環(huán)相比 while
要快 1.5 秒。
其中的差距主要在于兩者的機制不同。
在每次循環(huán)中,while
實際上比 for 多執(zhí)行了兩步操作:邊界檢查和變量 i 的自增。即每進行一次循環(huán),while
都會做一次邊界檢查(while i < n)
和自增計算(i +=1)。這兩步操作都是顯式的純 Python 代碼。
for 循環(huán)不需要執(zhí)行邊界檢查和自增操作,沒有增加顯式的 Python
代碼(純 Python 代碼效率低于底層的 C 代碼)。當(dāng)循環(huán)的次數(shù)足夠多,就出現(xiàn)了明顯的效率差距。
可以再增加兩個函數(shù),在 for 循環(huán)中加上不必要的邊界檢查和自增計算:
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
循環(huán)的執(zhí)行效率。
前面提到過,Python
底層的解釋器和內(nèi)置函數(shù)是用 C 語言實現(xiàn)的。而 C 語言的執(zhí)行效率遠大于 Python
。
對于上面的求等差數(shù)列之和的操作,借助于 Python
內(nèi)置的 sum
函數(shù),可以獲得遠大于 for
或 while 循環(huán)的執(zhí)行效率。
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
可以看到,使用內(nèi)置函數(shù) sum
替代循環(huán)之后,代碼的執(zhí)行效率實現(xiàn)了成倍的增長。
內(nèi)置函數(shù) sum
的累加操作實際上也是一種循環(huán),但它由 C 語言實現(xiàn),而 for 循環(huán)中的求和操作是由純 Python
代碼 s += i 實現(xiàn)的。C > Python
。
再拓展一下思維。小時候都聽說過童年高斯巧妙地計算 1 到 100 之和的故事。1…100 之和等于 (1 + 100) * 50。這個計算方法同樣可以應(yīng)用到上面的求和操作中。
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
的執(zhí)行時間約為 2.4e-6,縮短了上百萬倍。這里的思路就是,既然循環(huán)的效率低,一段代碼要重復(fù)執(zhí)行上億次。
索性直接不要循環(huán),通過數(shù)學(xué)公式,把上億次的循環(huán)操作變成只有一步操作。效率自然得到了空前的加強。
最后的結(jié)論:
實現(xiàn)循環(huán)的最快方式—— —— ——就是不用循環(huán)
對于 Python 而言,則盡可能地使用內(nèi)置函數(shù),將循環(huán)中的純 Python 代碼降到最低。
當(dāng)然,內(nèi)置函數(shù)在某些情況下還不是最快的。比如在創(chuàng)建列表的時候,是字面量寫法的速度更快
到此這篇關(guān)于Python 實現(xiàn)循環(huán)最快方式(for、while 等速度對比)的文章就介紹到這了,更多相關(guān)Python 實現(xiàn)循環(huán)最快方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
參考資料:
The Fastest Way to Loop in Python - mCoding (https://youtu.be/Qgevy75co8c)
相關(guān)文章
python模塊smtplib實現(xiàn)純文本郵件發(fā)送功能
這篇文章主要為大家詳細介紹了python模塊smtplib實現(xiàn)純文本郵件發(fā)送功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05