Pythonのジェネレーター(yield)とは?イテレーターの作り方を解説
生徒
「Pythonで大量のデータを順番に処理したいときって、どうやればいいんですか?」
先生
「そんなときに便利なのがジェネレーターです。yieldを使えば、データを一度に全部ではなく、必要な分だけ順番に取り出せます。」
生徒
「イテレーターって聞いたことがありますが、それと関係あるんですか?」
先生
「はい、ジェネレーターはイテレーターを作るための仕組みです。では実際の使い方を見ていきましょう。」
1. ジェネレーターとは?
ジェネレーターとは、Pythonで繰り返し処理できるオブジェクト(イテレーター)を簡単に作れる仕組みです。returnの代わりにyieldを使うことで、値を返したあと関数の実行状態を保持し、次回呼び出し時に続きから処理を再開します。
例えば、大きなファイルを行ごとに読み込む処理や、無限に続く数列を扱う処理に向いています。
2. yieldを使った基本的なジェネレーター
以下は1から3までの数字を順番に返すジェネレーターの例です。
def number_generator():
yield 1
yield 2
yield 3
for num in number_generator():
print(num)
1
2
3
yieldを使うことで、関数が一度に全ての値を返すのではなく、呼び出しごとに次の値を返します。
3. 大量データ処理でのメリット
通常のリストは全データをメモリに保持しますが、ジェネレーターは必要な分だけ生成するため、メモリ効率が良いです。
def read_lines():
for i in range(1, 6):
yield f"{i}行目のデータ"
for line in read_lines():
print(line)
1行目のデータ
2行目のデータ
3行目のデータ
4行目のデータ
5行目のデータ
この方法なら、大きなファイルでも一行ずつ処理でき、メモリ消費を最小限に抑えられます。
4. next()関数で手動制御
ジェネレーターはnext()関数を使って手動で値を取り出せます。
gen = number_generator()
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
1
2
3
最後の要素を取り出した後でさらにnext()を呼び出すと、StopIteration例外が発生します。
5. 無限ジェネレーターの例
ジェネレーターは条件を付けなければ無限に値を生成できます。
def infinite_counter():
num = 1
while True:
yield num
num += 1
counter = infinite_counter()
for _ in range(5):
print(next(counter))
1
2
3
4
5
この例では数が増え続けるため、使う側で終了条件を決める必要があります。
6. イテレーターとの関係
ジェネレーターは__iter__()と__next__()メソッドを自動で持つため、イテレーターの作成を簡単にする仕組みです。
通常のクラスでイテレーターを作ると複雑ですが、ジェネレーターならyieldを使うだけで簡潔に書けます。
7. 実用例:偶数だけを生成するジェネレーター
条件を加えることで、必要なデータだけを生成できます。
def even_numbers(limit):
for n in range(limit + 1):
if n % 2 == 0:
yield n
for n in even_numbers(10):
print(n)
0
2
4
6
8
10
無駄なデータを持たず、必要な値だけを順次生成できるのがジェネレーターの強みです。