1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Python 哪種方式循環(huán)最快,或許顛覆你的認(rèn)知!

        共 2219字,需瀏覽 5分鐘

         ·

        2022-03-04 00:49

        來源:StarryLand

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

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

        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

        這是一個(gè)簡(jiǎn)單的求和操作,計(jì)算從 1 到 n 之間所有自然數(shù)的總和??梢钥吹?for 循環(huán)相比 while 要快 1.5 秒。

        其中的差距主要在于兩者的機(jī)制不同。

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

        for 循環(huán)不需要執(zhí)行邊界檢查和自增操作,沒有增加顯式的 Python 代碼(純 Python 代碼效率低于底層的 C 代碼)。當(dāng)循環(huán)的次數(shù)足夠多,就出現(xiàn)了明顯的效率差距。

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

        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

        可以看出,增加的邊界檢查和自增操作確實(shí)大大影響了 for 循環(huán)的執(zhí)行效率。

        前面提到過,Python 底層的解釋器和內(nèi)置函數(shù)是用 C 語言實(shí)現(xiàn)的。而 C 語言的執(zhí)行效率遠(yuǎn)大于 Python。

        對(duì)于上面的求等差數(shù)列之和的操作,借助于 Python 內(nèi)置的 sum 函數(shù),可以獲得遠(yuǎn)大于 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í)行效率實(shí)現(xiàn)了成倍的增長(zhǎng)。

        內(nèi)置函數(shù) sum 的累加操作實(shí)際上也是一種循環(huán),但它由 C 語言實(shí)現(xiàn),而 for 循環(huán)中的求和操作是由純 Python 代碼 s += i 實(shí)現(xiàn)的。C > Python。

        再拓展一下思維。小時(shí)候都聽說過童年高斯巧妙地計(jì)算 1 到 100 之和的故事。1…100 之和等于 (1 + 100) * 50。這個(gè)計(jì)算方法同樣可以應(yīng)用到上面的求和操作中。

        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í)行時(shí)間約為 2.4e-6,縮短了上百萬倍。這里的思路就是,既然循環(huán)的效率低,一段代碼要重復(fù)執(zhí)行上億次。

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

        最后的結(jié)論(有點(diǎn)謎語人):

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

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

        參考資料

        The Fastest Way to Loop in Python - mCoding? (https://youtu.be/Qgevy75co8c)

        加入知識(shí)星球【我們談?wù)摂?shù)據(jù)科學(xué)】

        500+小伙伴一起學(xué)習(xí)!








        ·?推薦閱讀?·

        盤點(diǎn)2021最佳數(shù)據(jù)可視化作品

        「Python實(shí)用秘技04」pdf文件批量添加文字水印

        新一代Python包管理工具來了


        瀏覽 27
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            xxxx18一30岁hd热巴 | 国产精品宾馆 | 第一次做受被躁爽到高潮 | 一级片免费观看 | 在线看黄网 | 公交np肉多荤文高h少妇 | 色综合色婷婷 | 啪啪视频在线 | 99久久人妻精品免费二区 | 性69XXXX18XXXX九色 |