第 30 課 · 進階 · 20 分鐘

Python itertools

組合惰性迭代器,完成計數、拼接和分組。

itertoolscountchaingroupby

早高峰的訂單像一條長河,後廚卻按十份一批做。itertools 可以切片,又不用複製整條河。哪個工具分組時不會丟掉餘數?

itertools 為迭代器流水線提供小型積木。除非你主動要求,它們不會建立完整列表,因此很適合與生成器組合。先掌握 count、islice、chain 和 groupby,再用它們組合,而不是再寫一個索引迴圈。 你還會累積總量、用 tee 複製迭代器,並構造組合。

不用 range 也能計數

count 會產生無限序列。配合 islice 只請求固定數量的值。islice 適用於任何可迭代物件,不只是列表,而且回傳迭代器。

from itertools import count, islice
print(list(islice(count(10), 3)))

給無限序列加上邊界

用 chain 拼接可迭代物件

chain 會依次讀取一個可迭代物件,再讀取下一個,不建構中間列表。資料來自不同來源時很方便。只有需要列印或重複使用時,才用 list 包起來。

from itertools import chain
print(list(chain([1, 2], ["a", "b"])))

把多段合成一個流

分組相鄰的值

groupby 會把鍵相同的連續元素分到一組。它不會替你排序,所以相同鍵分散在各處時要先排序。分組結果是迭代器,必須在前進到下一個鍵之前消費完。

from itertools import groupby
data = [("a", 1), ("a", 2), ("b", 3)]
for key, group in groupby(data, key=lambda pair: pair[0]):
    print(key, list(group))

相同鍵的連續片段

accumulate 與 pairwise 派生流

accumulate 把值變成執行總量;pairwise 產出相鄰對。兩者都是惰性的,不用索引迴圈就能表達關係。累加器需要零這樣的起點時,用 initial=。

from itertools import accumulate, pairwise
values = [4, 3, 2]
print(list(accumulate(values)))
print(list(pairwise(values)))
print(list(accumulate(values, initial=0)))

執行總量與相鄰對

tee 複製迭代器,但會緩衝

tee 在一個源上回傳兩個獨立迭代器。它不是深拷貝:一個分支提前取走的值會為另一個分支緩衝。兩個分支都要消費;資料小到可以直接存下時,優先用列表。

from itertools import tee
values = iter([1, 2, 3])
a, b = tee(values)
print(list(a))
print(list(b))
print(list(a))

兩個讀者,一個帶緩衝的源

組合與笛卡爾積

combinations 選出不重複、無序的組合;product 構造輸入之間的所有配對。結果數量增長很快,所以輸入要小。它們適合測試矩陣和小型搜尋空間,不適合暴力列舉大資料。

from itertools import combinations, product
print(list(combinations(["a", "b", "c"], 2)))
print(list(product([1, 2], ["x", "y"])))

小型組合積木

本課要點

  • count 可以表示無限的等差序列。
  • islice 可以從任何可迭代物件中截取有限前綴。
  • chain 會把多個可迭代物件首尾相接。
  • groupby 分組相鄰元素;鍵分散時要先排序。
  • itertools 函式回傳迭代器,不是列表。
  • accumulate 和 pairwise 派生惰性流;tee 會緩衝;組合數量增長很快。

常見錯誤

  • 直接對 itertools 回傳的迭代器做下標存取。
  • 在前進 groupby 之前忘記消費目前分組。
  • 對未排序資料使用 groupby,卻期待全局分組。
  • 對超大流使用 tee,卻以為它完全不佔記憶體。
輪到你

列印 count(10) 的前三個值,再用 chain 拼接 [1, 2] 和 [3]。

動手試試

改改變數、先預測輸出,再執行程式碼。第一次點擊「執行程式碼」時會下載 Python 執行時,可能需要幾秒鐘。

瀏覽器內 Python本機執行 · 無需帳號
首次執行會從 CDN 下載 Pyodide。修改後點擊「執行程式碼」。

練習本課

12 道題,作答後立即看到解釋。

查看 12 道題答案開始練習
← dataclassescollections →