Python
のyield
キーワードは、メモリ効率の良いデータ処理を実現するために非常に役立ちます。通常の関数がreturn
によって最終的な結果を返すのに対して、yield
は関数の実行を一時的に停止し、値を返しながらその状態を保持します。この機能により、関数を再度呼び出すことなく、中断したところから実行を再開できます。
基本的な使い方
まず、yield
を使うとジェネレーター関数を定義できます。ジェネレーター関数を呼び出すと、すぐには処理が実行されず、ジェネレーターオブジェクトが返されます。このオブジェクトに対してnext()
を呼び出すたびに、yield
で指定された値が返され、関数の実行が一時停止します。
例
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
この例では、my_generator
関数が3つの値をyield
で返し、それぞれのnext()
呼び出しごとに次の値が生成されます。最後に値が生成された後、ジェネレーターはStopIteration
例外をスローし、処理が終了します。
メリット
yield
の最大の利点はメモリ効率です。通常のリストはすべての要素をメモリに保持しますが、ジェネレーターは必要なときに値を逐次生成するため、大量のデータを扱う際にメモリを節約できます。
例えば、以下のコードでは、100万個の数値の平方を生成するジェネレーターが作成されます。
def square_numbers(nums):
for num in nums:
yield num * num
numbers = square_numbers(range(1000000))
for num in numbers:
print(num)
このジェネレーターは、全ての平方数を一度にメモリに保持せず、1つずつ計算して返します。
ジェネレーターの活用例
ファイルの行を逐次読み込む
大きなファイルを扱うとき、ファイル全体を一度にメモリにロードすると非常に非効率です。ジェネレーターを使えば、ファイルの各行を逐次処理できます。
def read_file_in_chunks(file_name):
with open(file_name) as file:
for line in file:
yield line.strip()
for line in read_file_in_chunks('large_file.txt'):
print(line)
このように、ジェネレーターを使用することで、大量のデータを処理しながらメモリの消費を抑えつつ、効率的に動作させることができます。
yield
とreturn
の違い
return
は関数を終了させて値を返すのに対し、yield
は値を返しつつ関数の状態を保持します。ジェネレーター関数は、return
が呼び出されたり、yield
がもう存在しない場合にのみ終了します。
def example():
yield 1
return # ここで終了
yield 2 # 実行されない
gen = example()
print(next(gen)) # 1
yield
が値を返した後、関数は実行を停止しますが、完全には終了せず、次のnext()
の呼び出しで続行します。一方、return
は関数を完全に終了させ、以降のyield
は実行されません。
まとめ
yield
は、Python
でジェネレーターを作成するために使用され、メモリ効率の良いデータ処理を可能にします。大量のデータや無限シーケンスを扱う場合、yield
を使って必要な値を逐次生成することで、効率的なプログラムが実現できます。また、ジェネレーターを使うことでコードの可読性も向上し、シンプルかつ強力なデータ処理が可能です。