🍩

PythonのIteratorとIterableを理解:図とコードで整理

に公開

初めに

Pythonにおいて for 文による繰り返し処理は日常的に用いられていますが、その内部では「Iterable(イテラブル)」と「Iterator(イテレータ)」という2つの重要なプロトコルが動作しています。

本記事では、Python公式ドキュメント「Iterator Types」を基に、
これらの基本概念と実装の仕組みを 図解・コード例・補足解説を交えて説明します。

用語の定義と公式仕様の要約

Pythonにおける繰り返し処理は、以下の2つのメソッドにより実現されます:

種別 必須メソッド 概要
Iterable __iter__() イテレータを返す。for 文等で使用可能。
Iterator __iter__() , __next__() 1つずつ要素を返し、要素が尽きたら 例外としてStopIteration を発生させる。

iterator.__next__()
Return the next item from the iterator. If there are no further items, raise the StopIteration exception.
Once an iterator’s __next__() method raises StopIteration, it must continue to do so on subsequent calls.
Python Docs: Iterator Types

イテラブル (Iterable) になるには?

イテラブルとは、繰り返し処理(反復処理)可能なオブジェクトのことであり、
__iter__() メソッドを実装している必要がある

このメソッドは、イテレータオブジェクトを返す必要があるため、実質的に「イテレータを生成する仕組み」となる

代表的なイテラブル

  • list, tuple, set, dict, str
  • range() オブジェクト
  • ファイルオブジェクト など

イテレータ (Iterator) になるには?

イテレータとは、繰り返し処理の1つ1つの要素を取り出す機構です。
以下の2つのメソッドを同時に実装している必要があります:

  • __iter__():自分自身を返す(これにより for 文でも使える)
  • __next__():次の要素を返す。残り要素がない場合は StopIteration を発生させる

StopIteration の役割とは?

イテレータの __next__() メソッドが要素を返し終わった際、
繰り返しが終了したことを示すために StopIteration 例外を明示的に発生させる

この例外は、Python内部で自動的に補足されるため for 文では意識する必要はありませんが、
手動で next() を使う場合には try / except ブロックで補足することが一般的

try:
    print(next(it))
except StopIteration:
    print("もう要素はありません")

一度 StopIteration を発生したイテレータは、その後も StopIteration を返し続けなければならず、この仕様に反した実装は「壊れた実装」とみなされます。

複数タイプのイテレーションにも対応可能

1つのデータ構造に対して、複数の繰り返し方法を提供することも可能

例として、木構造(tree structure)に対し:

  • 深さ優先探索(DFS)
  • 幅優先探索(BFS)

など、異なるイテレータを返す複数のメソッド(例:iter_dfs()iter_bfs())を用意することで、柔軟な反復処理の設計が可能

図解:Iterable と Iterator の関係

          +-----------------------+
          |       Iterable        |   ← __iter__() を持つ
          |-----------------------|
          |  list, tuple, set     |
          |  dict, str, range     |
          +-----------------------+
                     |
                     | iter(obj)
                     v
          +-----------------------+
          |       Iterator        |   ← __next__() と __iter__() を持つ
          |-----------------------|
          |  1つずつ要素を返す     |
          |  next()で取り出せる    |
          +-----------------------+
                     |
                     | next()
                     v
            要素1 → 要素2 → ... → StopIteration

基本コード:iter() と next()

nums = [1, 2, 3]       # Iterable(list)
it = iter(nums)        # Iterator を生成

print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
print(next(it))  # StopIteration が発生

カスタムイテレータの実装例

class CountUpTo:
    def __init__(self, max):
        self.max = max
        self.current = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.current > self.max:
            raise StopIteration
        val = self.current
        self.current += 1
        return val

# 使用例
for i in CountUpTo(3):
    print(i)  # 1, 2, 3

for文の裏側で起きている処理

for x in [1, 2, 3]:
    print(x)

この構文は、実は以下のように書き換えることが可能:

it = iter([1, 2, 3])
while True:
    try:
        x = next(it)
        print(x)
    except StopIteration:
        break

応用:iter(callable, sentinel) の使用例

import random

rand_iter = iter(lambda: random.randint(0, 9), 7)

for num in rand_iter:
    print(num)  # 7が出るまで繰り返す

この形式の iter() は、終了条件が明示されていないような処理をイテレータとして抽象化する際に便利

用語まとめ

用語 説明
iter(obj) イテラブルからイテレータを生成する関数
next(it) イテレータから次の要素を取得する関数
StopIteration イテレータの終端を示すために使用される例外
raise 明示的に例外が発生させるPythonのキーワード

参考文献

おわり

  • Iterable は「繰り返し処理が可能なオブジェクト」
  • Iterator は「次の要素を返し、終了時には 例外としてStopIteration が発生するオブジェクト」
  • iter() / next() を活用することで、Pythonのループ処理の内部動作への理解が深まります
  • ジェネレータやストリーム処理といった応用にもつながる、重要な基礎概念

Discussion