ジェネレータ関数
yieldで値を遅延生成します
「ジェネレータ関数」はCoddyKit上の無料Python Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPython Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Python Academyコースには全4レッスンが含まれています。
ジェネレーターとは
ジェネレーター関数は通常の関数に似ていますが、returnの代わりに(またはreturnとともに)yieldを使います。ジェネレーター関数を呼び出しても本体は実行されず、イテレーターであるジェネレーターオブジェクトが返されます。
def gen():
yield 1
yield 2
yield 3
g = gen()
print(type(g).__name__)
print(list(g))yieldによる実行の一時停止
next()を呼び出すたびに、関数はyieldに到達するまで実行され、その値を返して状態を凍結します。次に呼び出すと、yieldの直後から実行が再開されます。
def steps():
print('start')
yield 'a'
print('resumed')
yield 'b'
g = steps()
print(next(g))
print(next(g))ジェネレーターをループする
ジェネレーターはイテレーターなので、forループが自動的に処理し、関数が終了すると停止します(内部ではStopIterationが発生します)。
def countdown(n):
while n > 0:
yield n
n -= 1
for x in countdown(4):
print(x)遅延評価
ジェネレーターは遅延評価されます。値は要求されたときにだけ生成されます。そのため、大規模なシーケンスや無限シーケンスも、大量のメモリを使わずに扱えます。
def naturals():
n = 1
while True:
yield n
n += 1
g = naturals()
print(next(g), next(g), next(g))yield間で保持される状態
ローカル変数の値はyieldの間で保持されます。ジェネレーターは中断した位置を自然に記憶するため、インデックスを手動で管理する必要はありません。
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
g = fib()
print([next(g) for _ in range(7)])ジェネレーターとリストの構築の違い
通常の関数はリスト全体を一度に構築して返します。ジェネレーターは要求されたときに項目を生成します。シーケンスが大きい場合や、途中で処理を停止する可能性がある場合は、ジェネレーターを使用します。
def squares_list(n):
result = []
for i in range(n):
result.append(i * i)
return result
def squares_gen(n):
for i in range(n):
yield i * i
print(squares_list(5))
print(list(squares_gen(5)))途中で停止する
生成は遅延評価されるため、ループを途中で抜けると、ジェネレーターは残りの値を計算しません。
def naturals():
n = 1
while True:
print('producing', n)
yield n
n += 1
for x in naturals():
if x > 3:
break
print('got', x)ジェネレーター内のreturn
ジェネレーター内の単独のreturnは、ジェネレーターを終了させるだけです(StopIterationが発生します)。返した値は例外のvalue属性になりますが、ほとんどのループでは無視されます。
def up_to(stop):
i = 0
while True:
if i >= stop:
return
yield i
i += 1
print(list(up_to(4)))ジェネレーターは一度しか使えない
すべてのイテレーターと同様に、ジェネレーターは一度消費されます。使い切った後は何も生成しません。新しいジェネレーターを取得するには、関数をもう一度呼び出します。
def gen():
yield 1
yield 2
g = gen()
print(list(g))
print(list(g))
print(list(gen()))ジェネレーターによるフィルタリング
ジェネレーターを使うと、すっきりしたデータパイプラインを構築できます。ここでは、偶数だけを一度に1つずつ生成します。
def evens(numbers):
for n in numbers:
if n % 2 == 0:
yield n
print(list(evens(range(10))))ジェネレーターの連結
あるジェネレーターで別のジェネレーターを消費し、各段階を遅延評価する多段パイプラインを構築できます。
def numbers(n):
for i in range(n):
yield i
def doubled(src):
for x in src:
yield x * 2
print(list(doubled(numbers(5))))理解度チェック
ジェネレーター関数の理解度を確認しましょう。
まとめ
ジェネレーター関数について学びました。
yieldは実行を一時停止・再開し、ローカル状態を保持します。- 関数を呼び出すと、遅延評価されるジェネレーターオブジェクトが返されます。
- メモリ効率に優れ、パイプラインや無限ストリームに適しています。
- 他のイテレーターと同様に、一度しか使用できません。
次は、さらに簡潔なジェネレーター式を学びます。
よくある質問
「ジェネレータ関数」レッスンは無料ですか?
はい。「ジェネレータ関数」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Python Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Python Academyコースには全4レッスンが含まれています。
「ジェネレータ関数」で何を学びますか?
yieldで値を遅延生成します ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Python Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのPython Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「ジェネレータ関数」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このPython Academyレッスンでコードを書いて実行できますか?
はい。すべてのPython Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- イテレータプロトコル
- ジェネレータ関数
- ジェネレータ式
- yield fromと委譲