potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

Python 3 イテレーターを任意の個数複製する(itertools.tee)

あまり使わない関数ですが、標準ライブラリのitertools.tee関数を使うとあるイテレーターから任意の個数の独立したイテレーターを作成できます。イテレーターは要素の取得のみで取得位置を戻せませんが、この関数を使えばある位置のイテレーターを保存できます。なお、itertools.tee関数に与えたイテレーターを進めると作成したイテレーターも変化することには注意してください。

イテレーターは要素の取得のみで取得位置を戻せないことを示すサンプルコードです。list関数はイテレーターの要素をすべて取得して末尾の要素の次に位置を進めるため、list関数を2回繰り返せません。

i = iter(range(0, 3))
list(i) # [0, 1, 2]
list(i) # []

itertools.tee関数による独立したイテレーターのサンプルコードです。itertools.tee関数はイテレーターの独立した複製を作成するため、各イテレーターはそれぞれlist関数を適用できます。なお、それぞれのイテレーターはlist関数を2回繰り返せません。

from pprint import pp
from itertools import tee

pp(tee(range(0, 10), 3))
# 戻り値はイテレーターのリスト
#(<itertools._tee object at 0x000001F54A5ECBC0>,
# <itertools._tee object at 0x000001F54A5ECC40>,
# <itertools._tee object at 0x000001F54A5ECC80>)

pp([list(i) for i in tee(range(0, 10), 3)])
# それぞれに`list`を適用できる。
#[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]

参考