INDEX
yieldの概要
ジェネレーター関数の中断と再開 Python予約語 | ||
yield 概要 わかりやすく説明 |
||
|
yieldの基本的な使い方
以下の例では、ジェネレーター関数を定義し、yield
を使って値を順番に返します。
# yield を使ったジェネレーター関数
def count_up():
for i in range(3):
yield i # ここで一時停止し、値を返す
gen = count_up()
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 2
yield i
により、一度に 1 つの値を返す。next()
を呼び出すたびに、前回の状態を保持しつつ次の処理を実行。
ジェネレーターの動作
ジェネレーターは、next()
を使うたびに1つずつ処理を進めます。
# next() の挙動
def simple_generator():
yield "A"
yield "B"
yield "C"
gen = simple_generator()
print(next(gen)) # A
print(next(gen)) # B
print(next(gen)) # C
print(next(gen)) # StopIteration 例外が発生
yield
によって “A” → “B” → “C” の順で値が返る。- すべての
yield
を通過すると、StopIteration
例外が発生。
forループでジェネレーターを処理する
for
ループを使うと、自動的にジェネレーターの next()
を呼び出して処理できます。
# forループでジェネレーターを処理
def count_down(n):
while n > 0:
yield n
n -= 1
for num in count_down(5):
print(num) # 5 4 3 2 1
for
ループが自動的にnext()
を呼び出し、値を取得。- ループ終了時に
StopIteration
が発生しても自動的に処理が終了。
yield を使った無限ループ
yield
を使うと、メモリ効率の良い無限ループを作成できます。
# 無限ループのジェネレーター
def infinite_counter():
n = 0
while True:
yield n
n += 1
counter = infinite_counter()
print(next(counter)) # 0
print(next(counter)) # 1
print(next(counter)) # 2
while True
を使って、無限に値を生成。next()
を呼び出すたびに次の値が得られる。
yield を使って値を受け取る
ジェネレーターに外部から値を送ることも可能です。
# send() でジェネレーターに値を送る
def echo():
while True:
received = yield
print(f"受信: {received}")
gen = echo()
next(gen) # ジェネレーターを開始
gen.send("Hello") # 受信: Hello
gen.send("Python") # 受信: Python
yield
の左辺に変数を指定すると、send()
で値を送信可能。next(gen)
を最初に呼び出してジェネレーターを開始する必要がある。
yield の注意点
- ジェネレーターは 1 度しかイテレーションできない: もう一度ループを回すには、新しくジェネレーターを作る必要がある。
- メモリ効率が良い: リストを返す関数よりも、大量のデータを扱う際に有利。
- デバッグが難しい: 状態を保持するため、途中の処理が把握しづらいことがある。
yield のよくある質問
- Q: yield と return の違いは?
- A:
return
は関数を完全に終了し、yield
は状態を保持したまま一時停止する。 - Q: yield のメリットは?
- A: 大量のデータを一度に処理せず、必要な分だけ遅延評価できるため、メモリ消費を抑えられる。
- Q: ジェネレーターをリストのように扱えますか?
- A:
list(generator)
を使えば、すべての要素をリストに変換できるが、メモリ効率の良さが失われる。
まとめ
yield
は、ジェネレーターを作成し、データを一時停止しながら処理できる強力なキーワードです。
- 関数の状態を保持しつつ、データを順次生成できる。
- 大規模データを効率的に処理するのに適している。
send()
を使えば、外部からデータを注入可能。
適切に yield
を活用し、効率的なデータ処理を実現しましょう。