Python ジェネレーター: メモリ効率の高いイテレーター

Python ジェネレーターと yield ステートメントを使用して、最小限のメモリ フットプリントで巨大なデータセットを処理する方法を学びます。ジェネレーター式をマスターします。

エディターで試してみる

概要

数千または数百万のレコードを処理するコードを作成する場合、メモリ管理が重要になります。データセット全体をリストに読み込むと、RAM が不足してサーバーがクラッシュする危険があります。 Python ジェネレーターは、オンデマンドでデータをストリーミングするメカニズムを提供することで、この問題を解決します。データセット全体を一度に計算してメモリに保存するのではなく、ジェネレーターは一度に 1 つの項目を生成し、それを呼び出し元に渡し、次の項目が要求されるまで実行を一時停止します。

ジェネレーターは通常の関数と同じように定義されますが、`return` の代わりに `yield` キーワードを使用します。ジェネレーター関数が呼び出されると、関数の内部ステートメントを実行せずにジェネレーター反復子オブジェクトを返します。呼び出し元がジェネレーターで `next()` を呼び出す (またはループする) と、関数は `yield` に到達するまで実行されます。その時点で、ジェネレーターは値を生成し、ローカル変数を保存し、実行を一時停止します。再度呼び出されると、中断したところから正確に再開されます。

また、ジェネレーター式を使用してジェネレーターを作成することもできます。ジェネレーター式は、リスト内包表記と同じ構文を使用しますが、括弧 `[...]` の代わりに括弧 `(...)` で囲みます。これにより、リスト内包表記をメモリ効率の高い反復子に置き換えるのが驚くほど簡単になります。大量のメモリ割り当てを回避することにより、ジェネレータは、大規模なログの操作、データベースからのデータのストリーミング、または無限長の数学的シーケンスの計算の実行に不可欠です。

コードと実行の出力

フィボナッチ数とメモリ効率の高いジェネレータ式を生成するカスタム ジェネレータ。

def fibonacci_generator(limit):
    """Yields Fibonacci numbers up to the limit."""
    a, b = 0, 1
    count = 0
    while count < limit:
        yield a
        a, b = b, a + b
        count += 1

# Instantiate generator
fib = fibonacci_generator(5)
print("--- Using Generator Function ---")
for num in fib:
    print(num)

# Generator expression (squares of numbers)
squares_gen = (x**2 for x in range(1, 1000000))
print("\n--- Using Generator Expression ---")
print(next(squares_gen))
print(next(squares_gen))
print(next(squares_gen))
端子出力
--- Using Generator Function ---
0
1
1
2
3

--- Using Generator Expression ---
1
4
9

段階的な実装

  • RAM に対して大きすぎるファイルを 1 行ずつ読み取る
  • ID または数学数値の無限シーケンスの生成
  • データベースレコードをバッチでストリーミングして API 呼び出しを処理する

よくある質問

利回りとリターンの違いは何ですか?

return は関数を完全に終了します。 yield は値を生成し、関数を一時停止してその状態を保存し、要求されたときに再開できるようにします。

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

StopIteration 例外が発生します。 「for」ループでは、Python はこの例外を自動的にインターセプトしてループを正常に終了します。

関連トピック

推奨される Python リソース

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