ジェネレータ: 遅延評価のイテレータ
巨大なデータを一度にメモリに載せず、必要な時に1つずつ生成。
ジェネレータ
yield で値を1つずつ返す関数。
yield
値を返して一時停止するキーワード。
遅延評価
必要になるまで計算しない仕組み。
ジェネレータとは?
ジェネレータは `yield` を使って「値を1つ返して一時停止」します。次に呼ばれるまで待機するため、無限の数列や巨大なファイルの処理でも、メモリをほとんど使いません。Pythonにおいて「巨大データ処理」の切り札です。
def count_up(start=0): n = start while True: yield n n += 1
counter = count_up()print(next(counter)) # 0print(next(counter)) # 1print(next(counter)) # 2Bad
# ❌ Bad: 全データをリストに読み込むdef read_all_lines(path): with open(path) as f: return f.readlines() # メモリに全行を保持
lines = read_all_lines("huge.log") # メモリ爆発!Good
# ✅ Good: ジェネレータで1行ずつdef read_lines(path): with open(path) as f: for line in f: yield line.strip()
for line in read_lines("huge.log"): # メモリ効率的 process(line)ジェネレータ式
# ジェネレータ式(リスト内包表記の () 版)squares_list = [x**2 for x in range(1000000)] # メモリに全部squares_gen = (x**2 for x in range(1000000)) # 遅延評価
# メモリ使用量の比較import sysprint(sys.getsizeof(squares_list)) # 約8MBprint(sys.getsizeof(squares_gen)) # 約200バイト Tip: リスト内包表記は [ ]、ジェネレータ式は ( )
パイプライン処理
# パイプライン処理def filter_even(nums): for n in nums: if n % 2 == 0: yield n
def double(nums): for n in nums: yield n * 2
numbers = range(10)result = double(filter_even(numbers))print(list(result)) # [0, 4, 8, 12, 16]合格ライン
yield でジェネレータを書ける
ジェネレータ式 () を使える
ジェネレータが使い捨てな理由を知っている
演習課題
課題1: yield
yield を使ってジェネレータを作成してください。
課題2: ジェネレータ式
ジェネレータ式で遅延評価を実装してください。