Python 哪種方式循環(huán)最快堪旧,顛覆你認知!

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

while 和 for 是 Python 中常用的兩種實現(xiàn)循環(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 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 之間所有自然數的總和」彝保可以看到 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)的次數足夠多累驮,就出現(xiàn)了明顯的效率差距酣倾。

可以再增加兩個函數,在 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 底層的解釋器和內置函數是用 C 語言實現(xiàn)的置侍。而 C 語言的執(zhí)行效率遠大于 Python映之。

對于上面的求等差數列之和的操作,借助于 Python 內置的 sum 函數蜡坊,可以獲得遠大于 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

可以看到,使用內置函數 sum 替代循環(huán)之后算色,代碼的執(zhí)行效率實現(xiàn)了成倍的增長抬伺。

內置函數 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 < 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)的效率低膏燕,一段代碼要重復執(zhí)行上億次。

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

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

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

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

小編不是在講廢話及舍,只是給剛學Python的小伙伴少走彎路的方法!?弑痢锯玛!

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市钾麸,隨后出現(xiàn)的幾起案子更振,更是在濱河造成了極大的恐慌炕桨,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肯腕,死亡現(xiàn)場離奇詭異献宫,居然都是意外死亡,警方通過查閱死者的電腦和手機实撒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門姊途,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人知态,你說我怎么就攤上這事捷兰。” “怎么了负敏?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵贡茅,是天一觀的道長。 經常有香客問我其做,道長顶考,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任妖泄,我火速辦了婚禮驹沿,結果婚禮上,老公的妹妹穿的比我還像新娘蹈胡。我一直安慰自己渊季,他們只是感情好,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布罚渐。 她就那樣靜靜地躺著却汉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪搅轿。 梳的紋絲不亂的頭發(fā)上病涨,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音璧坟,去河邊找鬼。 笑死赎懦,一個胖子當著我的面吹牛雀鹃,可吹牛的內容都是我干的。 我是一名探鬼主播励两,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼黎茎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了当悔?” 一聲冷哼從身側響起傅瞻,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤踢代,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后嗅骄,有當地人在樹林里發(fā)現(xiàn)了一具尸體胳挎,經...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年溺森,在試婚紗的時候發(fā)現(xiàn)自己被綠了慕爬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡屏积,死狀恐怖医窿,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情炊林,我是刑警寧澤姥卢,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站渣聚,受9級特大地震影響隔显,放射性物質發(fā)生泄漏。R本人自食惡果不足惜饵逐,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一括眠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧倍权,春花似錦掷豺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至默辨,卻和暖如春德频,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缩幸。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工壹置, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人表谊。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓钞护,卻偏偏與公主長得像,于是被迫代替她去往敵國和親爆办。 傳聞我的和親對象是個殘疾皇子难咕,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內容