Python でジェネレーターを使用する方法 (yield ステートメント)

Python でジェネレーターを作成する方法を学びます。 yield キーワード、遅延評価、メモリの最適化を理解し、ジェネレーターとリスト構造を比較します。

エディターでこのソリューションを試してください

概要

大規模なデータセット、ログ ファイル、または無限のデータ ストリームを操作する場合、すべての要素を同時にメモリにロードすると (大きなリストを返すなど)、システム RAM が簡単に使い果たされ、アプリケーションがクラッシュする可能性があります。 Python は、優れたメモリ効率の高いソリューションであるジェネレーターを提供します。

ジェネレーターは、遅延反復子を返す特別なタイプの関数です。すべての値を一度に計算して返すのではなく、ジェネレーターは要求に応じて値を 1 つずつ生成します。主な違いは「yield」ステートメントです。ジェネレーター関数が「yield」を呼び出すと、その実行状態 (変数、命令ポインター) を一時停止し、生成された値を返します。次の値が要求されると、関数は一時停止した場所から正確に再開します。

ジェネレーターの計算は遅延して実行されるため、データセットのサイズに関係なく、メモリの使用量はほぼゼロになります。 Python は、完全な関数を宣言せずに軽量のインライン ジェネレーターを作成するために括弧付き構文 `(x for x in data)` を使用するジェネレーター式もサポートしています。

コードと実行の出力

このスクリプトは、yield ステートメントとジェネレーター式を備えたジェネレーター関数を使用してシーケンスを生成する方法を示します。

# 1. Generator function using yield
def count_up_to(limit):
    count = 1
    while count <= limit:
        yield count
        count += 1

# Instantiating the generator
counter = count_up_to(3)
print("Memory safe generator instantiated.")

# Fetching values manually
print("Next 1:", next(counter))
print("Next 2:", next(counter))
print("Next 3:", next(counter))

# 2. Iterating with a for loop (automatically handles StopIteration)
print("\n--- Looping over generator ---")
for num in count_up_to(4):
    print("Num:", num)

# 3. Generator expression (Shorthand syntax)
squares_gen = (x**2 for x in range(1, 4))
print("\nGenerator expression elements:")
print(list(squares_gen)) # Cast to list to print all elements
端子出力
Memory safe generator instantiated.
Next 1: 1
Next 2: 2
Next 3: 3

--- Looping over generator ---
Num: 1
Num: 2
Num: 3
Num: 4

Generator expression elements:
[1, 4, 9]

段階的な実装

  • 標準の def キーワードを使用して関数を定義します。
  • 値を反復子ストリームに返すには、return の代わりに yield キーワードを使用します。
  • for ループを使用してジェネレーターを反復処理するか、組み込みの next(gen) 関数を呼び出して値を抽出します。
  • 単純なインライン遅延変換には、ジェネレーター式 (かっこを使用) を使用します。

よくある質問

リストに対するジェネレーターの主な利点は何ですか?

メモリ効率。リストはすべての要素を RAM に同時に保存しますが、ジェネレーターはオンデマンドで項目を 1 つずつ生成するため、システムの合計メモリより大きいデータセットを処理できます。

ジェネレーターのアイテムがなくなるとどうなりますか?

Python は StopIteration 例外を発生させます。 for ループはこの例外を自動的にキャッチしてループを正常に終了しますが、使い果たしたジェネレーターで next() を手動で呼び出すと例外がスローされます。

関連トピック

推奨される Python リソース

関連するインタラクティブなチュートリアル、チートシート、コード比較で知識を深めてください。