当サイトは、アフィリエイト広告を利用しています
Pythonの反復処理は、一見するとfor文だけで完結しているように見える。
しかし内部では明確な構造が存在する。
これらは別物である。
混同しやすいが、関係性は階層構造になっている。
Iterable└── Iterator└── Generator
また前提として、for文は内部的下記の構造で動いてる
it = iter(obj)while True:try:value = next(it)except StopIteration:break
この仕組みを理解すると
を理解することができる
当記事では
について、反復モデルの内部構造という観点から整理する。
イテラブルとは反復可能なオブジェクトのこと。
具体的には
といった反復可能なオブジェクトがイテラブルとなる。
つまりイテラブルは「材料」のこと
イテレータとは、イテラブルから生成される値を1つずつ返すオブジェクトである。
listを例にして説明すると
# イテラブル生成list = [1, 2, 3]# iter()を呼ぶとイテレータを返すit = iter(list)# イテレータから値を取得(next)print(next(it)) # 1print(next(it)) # 2print(next(it)) # 3print(next(it)) # StopIteration# イテラブル作成tuple = (1, 2, 3)# iter()を呼ぶとイテレータを返すit = iter(tuple)# イテレータから値を取得(for文)for value in it:print(value) # 1# 2# 3
つまりイテレータは「取り出し装置」である。
yieldによって作られるイテレータのこと。
つまりジェネレータはイテレータの一種である。
※ジェネレータはイテレータに含まれる
ジェネレータの生成方法は
の2種類ある
def generator():yield 1yield 2yield 3
generator = (value for value in list([1, 2, 3]))
yieldは
のように必要になった瞬間にだけ進む構造を実現する。
これを遅延評価と呼ぶ
つまりyieldは関数をジェネレータ関数に変える構文であり。 ジェネレータ関数が返すジェネレータは遅延評価を行うイテレータのことである。 ※遅延評価はイテレータの定義ではなく、ジェネレータの代表的な性質
遅延評価とは、
Pythonではジェネレータが代表例である。
# イテレータ生成lst = [x for x in list([1, 2, 3])]print(lst) # [1, 2, 3]
このコードではリスト内包表記が実行された瞬間に
すべての要素が計算され
メモリ上にリストが生成される
つまり、必要になる前に全要素を生成している(即時評価)
# ジェネレータ生成gen = (x for x in [1, 2, 3])print(gen) # <generator object ...>
値とりだす時に初めて計算される
print(next(gen)) # 1print(next(gen)) # 2print(next(gen)) # 3
Pythonの反復処理は
という役割分担の上に設計されている。
for 文は構文であり、その背後にはこの反復モデルが存在している。