0Pricing
Python Academy · レッスン

ジェネレータ関数

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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. イテレータプロトコル
  2. ジェネレータ関数
  3. ジェネレータ式
  4. yield fromと委譲
← Python Academyに戻る