最近在知乎上有人誤解了Python生成器的使用,在這裡我們來統一探討下它這麼用對不對。
舉一個例子,編寫一個函式計算一串數字裡所有偶數的個數,其實是很簡單的問題,但是有些人是用生成器這麼寫的:
In [66]: def f1(x):
....: return sum(c in '02468' for c in str(x))
....:
In [68]: x = int('1234567890'*50)
In [69]: %timeit f1(x)
10000 loops, best of 5: 52.2 µs per loop
生成器這麼用其實是速度最慢的一種做法,花費了52微秒。我們來看看如果我改成列表解析式會怎麼樣:
In [67]: def f2(x):
....: return sum([c in '02468' for c in str(x)])
....:
In [70]: %timeit f2(x)
10000 loops, best of 5: 40.5 µs per loop
你看,這個加速非常地明顯,僅花費了40.5微秒。
而且還能進一步改進, 如果我們改變之前定義的f2,讓它在列表解析式後判斷數字是否為偶數,是偶數才會成為最終生成的列表中的一員,這樣有另一個加速:
In [71]: def f3(x):
....: return sum([True for c in str(x) if c in '02468'])
....:
In [72]: %timeit f3(x)
10000 loops, best of 5: 34.9 µs per loop
34.9微秒,Perfect! 不僅如此,還能繼續加速!sum對於整數有一個快速路徑,但是這個快速路徑只啟用型別為int的變數. bool不行,因此我們把True改成1,能再加一次速!
In [73]: def f4(x):
....: return sum([1 for c in str(x) if c in '02468'])
....:
In [74]: %timeit f4(x)
10000 loops, best of 5: 33.3 µs per loop
Python實用寶典 (pythondict.com)
不只是一個寶典
歡迎關注公眾號:Python實用寶典
原文來自Python實用寶典:Python 生成器
本作品採用《CC 協議》,轉載必須註明作者和本文連結
Python實用寶典, pythondict.com