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 theStopIteration
exception.
Once an iterator’s__next__()
method raisesStopIteration
, 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