はじめに

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`の意味と挙動をチームが理解していることが前提になります。

構造の違い

UML Diagram
UML Diagram

図からも分かるように、イテレータは明示的な状態管理、ジェネレータは自動化された内部状態管理という特徴がある。

レビュー対象としての判断軸

レビューアーが判断すべき観点を、次のように整理できる。

観点 イテレータクラスに適したケース ジェネレータ関数が適したケース
状態の再利用 複数回の反復・外部との状態連携が必要 一度きりのシーケンス
状態管理の明示性 明示的に状態を持つ必要がある 状態を関数スコープ内に閉じたい
可読性と簡潔さ カスタム動作が多く読みやすさが必要な場合 単純な処理で簡潔な表現が優先される
テストしやすさ モックや状態変更を行いたい 処理結果だけ検証すれば良い構造
処理の中断と再開 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`が外部から参照されないにもかかわらず永続しており、状態が中途半端に内部化されています。状態保持の必要性を明示するため、クラス化も検討してください。

まとめ:レビューアーが押さえるべき設計視点

イテレータとジェネレータは、どちらを使うかが設計意図を表す
レビューアーは次のような視点から、設計の整合性と保守性を評価すべきである。

  • 状態管理の必要性はあるか?
  • 同じ処理を何度も使い回す想定か?
  • コードが読み手に意図を伝えているか?
  • テストの際に状態や進行状況を制御する必要があるか?

「何を使ったか」ではなく、「なぜそれを使ったか」。
この設計意図を読み解くことが、レビューアーの本質的な役割である。