【Python入門】イテレータとジェネレータをJava経験者向けにやさしく解説!

こんにちは。ゆうせいです。

今回は、Javaを学んだ新人エンジニアさんに向けて、Pythonの重要な機能である「イテレータ」と「ジェネレータ」について、基礎から丁寧に解説します。

「for文で配列回すだけでよくない?」と思ったあなた。実は、イテレータとジェネレータを使いこなせるようになると、メモリ効率のよいコード柔軟なループ処理が書けるようになります!

Javaの「Iteratorインターフェース」や「Iterable」と比較しながら、わかりやすく解説していきますね。


イテレータ(Iterator)とは?

Pythonにおけるイテレータの定義

Pythonでのイテレータは、繰り返し処理を行うための仕組みです。内部的には「次の値」を順番に返す「__next__() メソッド」を持ったオブジェクトのことを指します。

Javaでいうところのこの部分に近いです:

Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}

これに相当するPythonのコードはこうなります:

nums = [1, 2, 3]
it = iter(nums)  # イテレータを作成
print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3

ポイントは2つのメソッド

  • __iter__():イテラブル(繰り返し可能)なオブジェクトが呼び出す
  • __next__():次の値を返す(値が無ければ StopIteration を発生)

なぜ、Iteratorなのか?

「Iterator」は英語の「iterate(繰り返す)」に由来し、「反復処理を行う者」という意味を持ちます。プログラム内で、リストや文字列などの要素を一つずつ順番に取り出していく役割を持つため、まさに「繰り返しを行う存在」にふさわしい名前です。

特に、Pythonではnext()で要素を順に取り出す仕組みを担うため、「イテレーター」という単語はその動作を直感的に表しています。


ジェネレータ(Generator)とは?

「イテレータを簡単に作る方法」と考えよう!

Pythonのジェネレータとは、イテレータを自動で作ってくれる関数のようなものです。

イテレータを一から作るとクラス定義や状態管理が必要ですが、ジェネレータは yield を使うだけで、その処理を一時停止しながら値を順番に返すことができます。

Javaに例えるなら、Javaには直接的なyieldは無いですが、状態を保持しながら都度値を返すコルーチンのようなイメージです。

def count_up_to(n):
    i = 1
    while i <= n:
        yield i
        i += 1

この関数を呼び出すと、イテレータが返ってきます:

counter = count_up_to(3)
print(next(counter))  # 1
print(next(counter))  # 2
print(next(counter))  # 3

なぜ、Generatorなのか?

「Generator」は「生成するもの」という意味の英単語で、データをその場で一つずつ「生成(generate)」して渡す仕組みを表しています。Pythonでは、関数内でyieldを使うことで、値を逐次的に生成し、必要なときだけ出力できるようになります。

大量のデータを一括で渡すのではなく、必要に応じて逐次的に生成・提供するという点から、「Generator」という言葉が適しているといえます。


「return」ではなく「yield」が肝!

  • return は一回で関数を終了する
  • yield は一時停止して次の値へ進める

なぜ、yieldなのか?

「yield(イールド)」という単語は、英語で「産出する」「譲り渡す」という意味を持ちます。Pythonにおいては、関数の実行を一時停止して「値をいったん外へ渡す」ことを表しています。これは普通の関数がreturnで一度きりの値を返して終了するのに対し、yieldを使うと値を順番に「産出」しながら関数を中断・再開できるという特徴にぴったり合います。

まるでベルトコンベアから一つずつ品物を取り出すように、値を少しずつ渡す――その動作を表現する言葉として「yield」が採用されたと考えられます。


イテレータ vs ジェネレータ 比較表

機能イテレータジェネレータ
書き方クラス定義で __iter__ / __next__def 関数+yield
状態管理手動(変数を保持する必要あり)自動(Pythonが内部で保持)
簡単さやや複雑とても簡単
使い所複雑な繰り返しロジックシンプルにしたいとき

実践:リストの要素を2倍にして出力するジェネレータ

def double_values(lst):
    for value in lst:
        yield value * 2

nums = [1, 2, 3, 4]
for item in double_values(nums):
    print(item)

このように、yield を使うだけで「メモリを圧迫せずに処理を1つずつ行うこと」ができます。


メリット・デメリット

イテレータのメリット・デメリット

メリット

  • 柔軟にカスタマイズできる
  • 自分で状態をコントロールしやすい

デメリット

  • 実装がやや面倒(初心者にはとっつきにくい)

ジェネレータのメリット・デメリット

メリット

  • 書くのがとにかく楽
  • メモリ効率が良い(大量データに最適)

デメリット

  • 状態を細かく制御するのには不向きなこともある


最後に:これからどう学べばいい?

イテレータとジェネレータは、Pythonの「Pythonic(パイソニック)な書き方」をするうえで欠かせません。Javaと違って、for文の裏でどう動いているかを知ると、コードがもっと読みやすく・書きやすくなります。

次のステップとしては、以下をおすすめします!

  • map()filter()zip() といった「イテレータ系組み込み関数」の習得
  • ジェネレータ内で yield from を使った入れ子構造
  • 非同期ジェネレータ(async defyield)の活用(上級)

「Pythonは簡単」ってよく聞くけど、こういう仕組みを知ってはじめて“本当のやさしさ”が見えてきます。

一歩ずつ、一緒に学んでいきましょう!

セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。