Python|generator遅延評価を安全に設計する技法
この記事のポイント
- generator遅延評価の設計整理をレビュー視点で体系理解できる
- 状態管理、リソース開放、例外責務整理の技法を学べる
- 実務でのgenerator利用文化を体系化できる
- PlantUMLで依存構造と状態保持責任を可視化整理できる
そもそもgeneratorとは
Pythonのgeneratorは「イテレータを遅延生成する構造」です。
yield文を使うことで中断・再開可能な制御構造を提供します。
- 全件リスト展開せず逐次処理
- メモリ使用量抑制
- 状態保持による中間処理省略
generator基本例
def count_up_to(n):
i = 0
while i < n:
yield i
i += 1
for num in count_up_to(5):
print(num)- 各要素を順次生成
forループで自動的にnext()呼出
なぜこれをレビューするのか
generator設計は「状態保持責務が隠蔽されやすい」危険性を持ちます。
レビューアーは以下の整理視点を持つ必要があります。
レビューアー視点
- generator内に副作用処理が混入していないか
- リソース管理責務が漏洩していないか
- 中断再開可能性が設計的に考慮されているか
- イテレーション途中中断後の状態保持責務が破綻していないか
- 例外制御が中断復帰不能になっていないか
開発者視点
- 遅延評価のコスト構造を意識しきれない
- yield内にDB・API呼出を埋め込みがち
- finally開放責務を設計せず放置
- for文に隠蔽され実態を軽視しがち
generator崩壊の典型設計臭
崩壊しやすいパターン
- ファイル/DB接続をopenしたままyield
- 外部API呼出を逐次yieldで遅延呼出
- 例外発生時にfinally不在でリソース破棄漏れ
- 状態更新含むyieldで中断不整合
- ネストgeneratorで状態肥大化
崩壊例:リソース保持漏洩型
リソース漏洩例
def read_lines(file_path):
f = open(file_path)
for line in f:
yield line
@Reviewerファイルオープン状態がyield外に保持されています。with構文併用で開放責任を整理してください。
問題点
- イテレーション完了保証が前提
- 中断時にファイルクローズ未保証
崩壊構造モデル:リソース漏洩構造
generator設計整理の原則
以下の遅延評価設計文化が健全性維持に有効です。
① with構文融合文化
- リソースopen → yield はwith内で閉じる
② yield前後責務明示文化
- yield直前直後の副作用設計を明示
③ finally開放責務文化
- 状態保持系は必ずfinally整理
④ 中断安全文化
- for中断/例外発生時も設計上回復可能化
⑤ 状態更新分離文化
- 状態変更はyield内に混入しない
改善例:with融合整理版
with整理版
def read_lines(file_path):
with open(file_path) as f:
for line in f:
yield line「with文化+yield責務分離文化」
レビューアーは「yield前後副作用文化」を徹底確認すると設計臭抑止できます。
改善構造モデル:リソース安全整理
良くない実装例: ケース1(副作用混入)
副作用混入例
def process_items(items):
for item in items:
db.insert(item)
yield item
@Reviewer副作用(DB書込)がyield中に混在しています。副作用分離整理してください。
問題点
- yield中断で処理保証崩壊
- 副作用非再現性発生
改善例:副作用分離整理
副作用分離版
def generate_items(items):
for item in items:
yield item
def process_and_store(items):
for item in generate_items(items):
db.insert(item)- generatorは純粋データ流に限定
- 副作用は呼出側に外出し整理
良くない実装例: ケース2(ネスト状態肥大)
ネスト肥大例
def nested_generator():
for x in outer_source():
for y in inner_source(x):
yield transform(x, y)
@Reviewerネストyieldにより状態肥大が発生しています。段階分離整理してください。
問題点
- 状態伝播負荷上昇
- 再現検証困難化
改善例:段階分離整理版
段階分離版
def generate_outer():
for x in outer_source():
yield x
def generate_inner(x):
for y in inner_source(x):
yield y
def generate_combined():
for x in generate_outer():
for y in generate_inner(x):
yield transform(x, y)- 各層を独立責務に分離整理
- 読解・検証容易化
良くない実装例: ケース3(finally欠落)
finally欠落例
def resource_stream(resource):
resource.connect()
try:
while True:
yield resource.read()
finally:
resource.disconnect()
@Reviewerfinallyは正しいですがyield前のconnectが分離不全です。with文化整理を優先検討してください。
問題点
- 入口責務も構造化未整理
- 呼出構造依存が強い
改善例:contextmanager統合整理
context整理版
from contextlib import contextmanager
@contextmanager
def resource_manager(resource):
resource.connect()
try:
yield resource
finally:
resource.disconnect()
def resource_stream(resource):
with resource_manager(resource) as res:
while True:
yield res.read()- 初期化〜開放を構造統制化
- 呼出側中断安全化
観点チェックリスト
まとめ
generator設計は「状態設計と副作用制御の訓練場」そのものです。
レビューアーは「副作用分離文化・リソース責務文化・中断安全文化」を育成指導することで、
保守可能性の高い堅牢な遅延評価設計を育てられます。

