イテレータとジェネレータの使い分けをレビューでどう見抜くか
はじめに
Pythonでは、繰り返し処理を抽象化する手段としてイテレータ(iterator)とジェネレータ(generator)が提供されている。
どちらもfor文などに組み込める点で似ているが、設計上の責務・使い所・可読性においては明確な違いが存在する。
レビューアーはこれらを単なる文法としてではなく、「繰り返し処理の構造と責任分離」という設計の観点から捉え、どちらがより妥当かを判断できなければならない。
例1:イテレータプロトコルによるクラス設計
__iter__と__next__を用いたイテレータ
class Counter:
def __init__(self, max_val):
self.current = 0
self.max_val = max_val
def __iter__(self):
return self
def __next__(self):
if self.current >= self.max_val:
raise StopIteration
self.current += 1
return self.currentこの設計では、状態(self.current)を持った反復可能オブジェクトを提供している。
初学者には理解しづらいが、状態が明確に管理される点でテスト性やカスタマイズ性が高い。
Comment
@Reviewer: 明示的に状態管理が必要なケース(例:外部リソースの逐次取得など)にはイテレータクラスが適しますが、単純な数列処理では冗長になる可能性もあります。例2:ジェネレータ関数による簡潔な設計
yieldを用いたジェネレータ関数
def counter(max_val):
current = 0
while current < max_val:
current += 1
yield currentこちらは、状態の保持を関数スコープ内に閉じ込めた遅延評価処理である。
コード量も少なく、読みやすく、実行時のメモリ効率も良い。
Comment
@Reviewer: 明示的な状態制御や途中停止が不要な場合、ジェネレータの方が構造的に自然です。`yield`の意味と挙動をチームが理解していることが前提になります。構造の違い
図からも分かるように、イテレータは明示的な状態管理、ジェネレータは自動化された内部状態管理という特徴がある。
レビュー対象としての判断軸
レビューアーが判断すべき観点を、次のように整理できる。
| 観点 | イテレータクラスに適したケース | ジェネレータ関数が適したケース |
|---|---|---|
| 状態の再利用 | 複数回の反復・外部との状態連携が必要 | 一度きりのシーケンス |
| 状態管理の明示性 | 明示的に状態を持つ必要がある | 状態を関数スコープ内に閉じたい |
| 可読性と簡潔さ | カスタム動作が多く読みやすさが必要な場合 | 単純な処理で簡潔な表現が優先される |
| テストしやすさ | モックや状態変更を行いたい | 処理結果だけ検証すれば良い構造 |
| 処理の中断と再開 | StopIteration制御などが必要 |
yieldだけで制御できる |
ジェネレータ使用の是非を問う
状態を持つ処理での議論
def lines_with_prefix(file, prefix):
for line in file:
if line.startswith(prefix):
yield line
@Reviewer`yield`の使用は良いですが、途中でファイルを巻き戻すような仕様変更が入る場合は、クラス化して状態を保持する必要が出てきます。@Developer今は巻き戻し予定はありませんが、将来的にファイル位置の管理が必要になったら変更します。@Reviewer現時点ではこの設計で問題ありませんが、状態管理要件が発生したらイテレータへの移行を検討しましょう。
間違いやすいパターンとレビュー提案
暗黙の状態を持ったジェネレータ
def stream_data():
cache = []
for item in slow_source():
cache.append(item)
yield itemこのように、状態を伴う処理をyieldに埋め込むと、意図が見えづらくなる。
レビューでは「状態の永続性や副作用の有無」を確認し、適切な構造へ導く必要がある。
Comment
@Reviewer: `cache`が外部から参照されないにもかかわらず永続しており、状態が中途半端に内部化されています。状態保持の必要性を明示するため、クラス化も検討してください。まとめ:レビューアーが押さえるべき設計視点
イテレータとジェネレータは、どちらを使うかが設計意図を表す。
レビューアーは次のような視点から、設計の整合性と保守性を評価すべきである。
- 状態管理の必要性はあるか?
- 同じ処理を何度も使い回す想定か?
- コードが読み手に意図を伝えているか?
- テストの際に状態や進行状況を制御する必要があるか?
「何を使ったか」ではなく、「なぜそれを使ったか」。
この設計意図を読み解くことが、レビューアーの本質的な役割である。

