このページで解説している内容は、以下の YouTube 動画の解説で見ることができます。
【Python入門】ジェネレータ関数とyield 文

ジェネレータ関数とyield 文
ジェネレータ関数は、通常の関数とは異なり、一度にすべての値を返すのではなく、必要なときに1個ずつ値を「生成」する関数です。これにより、大量のデータや無限シーケンスを効率的に扱うことができ、メモリ消費を大幅に抑えられます。ここでは、ジェネレータ関数とyield文の基本概念から、より高度なyield from文を使った例まで、具体的なサンプルプログラムとともに解説します。

プログラムのダウンロード
「ダウンロード」から、JupyterLab で実行できるサンプルプログラムがダウンロードできます。ファイルは、ESET Endpoint Securityでウイルスチェックをしておりますが、ダウンロードとプログラムの実行は自己責任でお願いいたします。
1.ジェネレータ関数とyield文の基本
1.1. ジェネレータ関数とは
ジェネレータ関数は、関数定義内でreturn文の代わりにyield文を使うことで、呼び出し時にジェネレータオブジェクトを返します。
通常の関数とジェネレータ関数の違いは以下の表のとおりです。
項目 | 通常の関数 | ジェネレータ関数 |
---|---|---|
戻り値 | 1つの値(またはNone) | ジェネレータオブジェクト |
値の返し方 | return文で一度に返す。 | yield文で必要なときに1個ずつ返す。 |
メモリ使用 | 全結果を一度に保持する。 | 逐次生成するためメモリ効率が良い。 |
1.2. yield文の役割
yield文は、関数の実行を一時停止し、指定した値を返すキーワードです。次回ジェネレータから値を要求されると、yield文の直後から実行が再開されます。これにより、計算結果をその都度生成しながら、処理を続けることが可能になります。
2.ジェネレータ関数の実践例
2.1. 単純なジェネレータ関数の例:立方数の生成
ここでは、1から10までの整数の立方数を順に生成するジェネレータ関数を定義します。
def cube_generator():
for n in range(1, 11):
yield n ** 3
# ジェネレータ関数の呼び出しで得られるジェネレータオブジェクトをfor文で反復処理
for cube in cube_generator():
print(cube, end=' ')
print() # 改行
実行結果
1 8 27 64 125 216 343 512 729 1000
解説
- 関数cube_generator()は、1から10までの整数nについて、nの3乗(n ** 3)をyield文で返します。
- この関数を呼び出すと、すぐにはすべての値は計算されず、for文で各値が要求されるたびに順次計算されます。
- 結果として、1, 8, 27, …, 1000といった立方数が順に出力されます。
2.2. yield from文を使ったジェネレータ関数の例:カスタム範囲関数
yield from文を用いると、別のジェネレータから値をまとめて取り出すことができます。ここでは、開始値から終了値までの整数を生成するカスタム関数 custom_range() を定義し、それを利用して複数回同じ範囲の数値を生成する関数 custom_range_repeat() を作成します。
def custom_range(start, stop):
x = start
while x < stop:
yield x
x += 1
def custom_range_repeat(start, stop, times):
# times回、custom_rangeから値をyield fromで取り出す
for _ in range(times):
yield from custom_range(start, stop)
# custom_range_repeat関数を使って、3回繰り返し1から5までの整数を生成する
for num in custom_range_repeat(1, 6, 3):
print(num, end=' ')
print() # 改行
実行結果
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
解説
- custom_range() 関数は、startからstop-1までの整数をyield文で順に返します。
- custom_range_repeat() 関数では、for文で指定回数(times)だけループし、その都度yield from文を使ってcustom_range()のすべての値を取り出します。
- これにより、たとえば start=1, stop=6, times=3 の場合、1から5までの整数が3回連続で生成され、最終的な出力は
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
となります。
まとめ
ジェネレータ関数とyield文を活用すると、必要なときに値を逐次生成できるため、メモリ効率の良いプログラムを書くことができます。
- 通常の関数ではreturn文で1度に全結果を返しますが、ジェネレータ関数はyield文を用いて1個ずつ値を返すため、巨大なデータや無限シーケンスの処理に適しています。
- さらに、yield from文を使えば、既存のジェネレータから効率よく値を取り出し、より複雑な処理をシンプルに記述することが可能です。
これらの技法を習得することで、柔軟かつ効率的なデータ生成が実現でき、Pythonプログラミングの幅が大きく広がります。