<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Python 實現(xiàn)循環(huán)的最快方式(for、while 等速度對比)

          共 2589字,需瀏覽 6分鐘

           ·

          2021-12-01 20:17

          △點擊上方“Python貓”關注 ,回復“1”領取電子書
          作者:StarryLand
          來源:https://www.starky.ltd/2021/11/23/the-fastest-way-to-loop-in-python

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

          whilefor 是 Python 中常用的兩種實現(xiàn)循環(huán)的關鍵字,它們的運行效率實際上是有差距的。比如下面的測試代碼:

          import?timeit


          def?while_loop(n=100_000_000):
          ????i?=?0
          ????s?=?0
          ????while?i?????????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 代碼)。當循環(huán)的次數(shù)足夠多,就出現(xiàn)了明顯的效率差距。

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

          import?timeit


          def?while_loop(n=100_000_000):
          ????i?=?0
          ????s?=?0
          ????while?i?????????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?????????????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ù),可以獲得遠大于 forwhile 循環(huán)的執(zhí)行效率。

          import?timeit


          def?while_loop(n=100_000_000):
          ????i?=?0
          ????s?=?0
          ????while?i?????????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。這個計算方法同樣可以應用到上面的求和操作中。

          import?timeit


          def?while_loop(n=100_000_000):
          ????i?=?0
          ????s?=?0
          ????while?i?????????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)的效率低,一段代碼要重復執(zhí)行上億次。

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

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

          實現(xiàn)循環(huán)的最快方式—— —— ——就是不用循環(huán)

          對于 Python 而言,則盡可能地使用內(nèi)置函數(shù),將循環(huán)中的純 Python 代碼降到最低。

          當然,內(nèi)置函數(shù)在某些情況下還不是最快的。比如在創(chuàng)建列表的時候,是字面量寫法的速度更快:Python 疑難問題:[] 與 list() 哪個快?為什么快?快多少呢?

          參考資料

          The Fastest Way to Loop in Python - mCoding? (https://youtu.be/Qgevy75co8c)
          Python貓技術交流群開放啦!群里既有國內(nèi)一二線大廠在職員工,也有國內(nèi)外高校在讀學生,既有十多年碼齡的編程老鳥,也有中小學剛剛入門的新人,學習氛圍良好!想入群的同學,請在公號內(nèi)回復『交流群』,獲取貓哥的微信(謝絕廣告黨,非誠勿擾?。?/span>~


          還不過癮?試試它們




          說說 Python 的元編程

          在手機上 Python 編程,可以試試它!

          10 個“瘋狂”的 Python 項目創(chuàng)意

          11 個最佳的 Python 編譯器和解釋器

          Python 之父為什么嫌棄 lambda 匿名函數(shù)?

          80 個例子,徹底掌握Python日期時間處理!


          如果你覺得本文有幫助
          請慷慨分享點贊,感謝啦!
          瀏覽 43
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品V无码A片在线看吃奶 | 性爱激情五月 | 69一区二区 | 色欲av伊人久久大香线蕉影院 | 天天操天天日天天干 |