1. はじめに
Pythonはシンプルで直感的な構文を持つプログラミング言語ですが、より効率的にデータを扱うためには「イテレータ(iterator)」の概念を理解することが重要です。本記事では、イテレータの基本概念から実際の使い方、さらには応用例までを詳しく解説していきます。
2. イテラブルとイテレータの基本
Pythonにおいて、データを扱う際に重要なのが 「イテラブル(iterable)」 と 「イテレータ(iterator)」 です。この2つの違いを理解することで、forループの内部動作や、より高度なデータ処理の手法を学ぶことができます。
イテラブルとは?
イテラブル(iterable) とは、繰り返し処理が可能なオブジェクト のことを指します。Pythonでは、リストやタプル、辞書、セット、文字列などがイテラブルなオブジェクトに該当します。
イテラブルなオブジェクトは、for
ループを用いて順番に要素を取り出すことができます。
# リスト(イテラブル)の例
numbers = [1, 2, 3, 4, 5]
for num in numbers:
print(num)
このように、リスト numbers
は for
ループで簡単に処理できます。Pythonの for
ループの内部では、このイテラブルをイテレータに変換して要素を順番に取得しています。
イテレータとは?
イテレータ(iterator) とは、イテラブルなオブジェクトから要素を1つずつ取り出すための仕組みを持ったオブジェクト のことです。Pythonでは、iter()
関数を使うことで、イテラブルなオブジェクトをイテレータに変換できます。
numbers = [1, 2, 3, 4, 5]
iterator = iter(numbers) # イテレータを作成
print(next(iterator)) # 1
print(next(iterator)) # 2
print(next(iterator)) # 3
ここで next(iterator)
を呼び出すことで、リストの要素が順番に取得されていることがわかります。
3. Pythonにおけるイテレータの仕組み
Pythonのイテレータは、特定のメソッドを持つオブジェクトとして実装されています。
__iter__()
と __next__()
の役割
イテレータオブジェクトは、以下の2つの特別なメソッドを持ちます。
__iter__()
:オブジェクト自身を返す__next__()
:次の要素を返し、最後に到達するとStopIteration
を発生させる
例えば、リストを使って手動でイテレータを扱うと、次のようになります。
class CustomIterator:
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.current >= self.end:
raise StopIteration
value = self.current
self.current += 1
return value
# イテレータを作成
custom_iter = CustomIterator(1, 5)
for num in custom_iter:
print(num) # 1, 2, 3, 4 が順番に出力される
このように、カスタムイテレータを作成することで、for
ループを使ってデータを順番に取得できます。
4. イテレータの実装方法
Pythonでは、イテレータを独自に実装することで、柔軟なデータ処理が可能になります。本章では、独自のイテレータクラスの作成方法、ジェネレータ関数の活用、ジェネレータ式の利用 について詳しく解説します。
独自のイテレータクラスの作成
Pythonのイテレータは、__iter__()
メソッドと __next__()
メソッドを持つクラスとして実装できます。
次のコードは、1から指定された数値まで順番に値を返す独自のイテレータを作成する例です。
class Counter:
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
return self # 自身をイテレータとして返す
def __next__(self):
if self.current > self.end:
raise StopIteration # 終了時に例外を発生
value = self.current
self.current += 1
return value
# イテレータを作成し、forループで利用
counter = Counter(1, 5)
for num in counter:
print(num) # 1, 2, 3, 4, 5
ポイント:
__iter__()
メソッドはself
を返す(イテレータ自身がイテレータであるため)__next__()
メソッドは、現在の値を返しつつ次の値に更新する- 要素がなくなると
StopIteration
を発生させる
この方法で、カスタムイテレータを定義し、データのストリーム処理などに活用できます。
ジェネレータ関数の活用
Pythonでは、イテレータを作成するために ジェネレータ関数 を使用できます。
ジェネレータ関数は、yield
を使うことで、手軽にイテレータを作成できます。
def counter(start, end):
current = start
while current <= end:
yield current # 値を返しつつ実行状態を保持
current += 1
# ジェネレータ関数を使用
for num in counter(1, 5):
print(num) # 1, 2, 3, 4, 5
ジェネレータ関数の利点:
yield
を使うことで、値を返しつつ次回呼び出し時に処理を再開できる- メモリ消費を抑えつつ、必要なデータを逐次取得できる(遅延評価)
特に、大規模なデータ処理やストリーム処理 でジェネレータがよく使われます。
ジェネレータ式の利用
Pythonには、リスト内包表記と似た構文でジェネレータを作成する「ジェネレータ式」 があります。
# リスト内包表記(全ての要素をメモリに格納)
numbers_list = [x * 2 for x in range(1, 6)]
print(numbers_list) # [2, 4, 6, 8, 10]
# ジェネレータ式(遅延評価でメモリを節約)
numbers_gen = (x * 2 for x in range(1, 6))
print(next(numbers_gen)) # 2
print(next(numbers_gen)) # 4
ジェネレータ式の利点:
- リスト内包表記よりメモリ効率が良い
- 必要な要素のみを計算して取り出せる(遅延評価)
ジェネレータ式は、データ処理のパフォーマンス向上に貢献 するため、大量のデータを扱う場面で積極的に活用できます。

5. イテレータの応用例
イテレータを利用することで、さまざまな処理を効率的に実装できます。本章では、実務で役立つ3つの応用例 を紹介します。
① ファイルの逐次読み込み
大きなファイルを扱う際、一度にメモリに読み込むのは非効率です。
イテレータを活用すれば、ファイルを1行ずつ処理できます。
def read_large_file(file_path):
with open(file_path, "r", encoding="utf-8") as file:
for line in file:
yield line.strip() # 各行を逐次処理
# 使い方
for line in read_large_file("data.txt"):
print(line)
メリット:
- メモリを節約しつつ、大きなファイルを処理可能
- データのストリーム処理に適している
② 無限シーケンスの生成
イテレータを使うと、無限に続くシーケンスを効率的に生成できます。
def infinite_counter(start=0):
while True:
yield start
start += 1
# 無限ループにならないように制限をつけて利用
counter = infinite_counter()
for _ in range(5):
print(next(counter)) # 0, 1, 2, 3, 4
活用例:
- 時間ベースのデータストリーム
- センサーデータのリアルタイム処理
③ データストリームの処理
APIやデータベースからのデータを逐次処理する場合にも、イテレータが有効です。
import time
def api_simulation():
for i in range(1, 6):
time.sleep(1) # 1秒待機(API応答をシミュレート)
yield f"Data {i}"
# APIからのデータを逐次取得
for data in api_simulation():
print(data)
ポイント:
- データを リアルタイムで処理 しながら取得できる
- ネットワーク負荷を軽減しつつデータを扱える
6. イテレータ使用時の注意点
Pythonのイテレータは便利ですが、正しく使わないと予期しない挙動が発生することがあります。本章では、イテレータを扱う際に注意すべき 「StopIterationの扱い」「一度消費されたイテレータの再利用」「メモリ効率と遅延評価」 の3つのポイントについて解説します。
① StopIteration の扱い
イテレータを next()
で操作する際、すべての要素を取得し終えると StopIteration
例外が発生します。
numbers = [1, 2, 3]
iterator = iter(numbers)
print(next(iterator)) # 1
print(next(iterator)) # 2
print(next(iterator)) # 3
print(next(iterator)) # StopIteration が発生
この例外を適切に処理するには、try-except
を使用するのがベストです。
numbers = [1, 2, 3]
iterator = iter(numbers)
while True:
try:
print(next(iterator))
except StopIteration:
print("イテレータが終了しました")
break
ポイント
for
ループではStopIteration
は自動処理されるため、明示的に対処する必要はないnext()
を手動で使う場合はtry-except
で対処すると安全
② 一度消費されたイテレータの再利用
Pythonのイテレータは、一度すべての要素を取得すると再利用できません。
numbers = [1, 2, 3]
iterator = iter(numbers)
for num in iterator:
print(num) # 1, 2, 3 を出力
for num in iterator:
print(num) # 何も出力されない(イテレータは空になっている)
イテレータを再利用する場合は、新しく作成し直す必要があります。
numbers = [1, 2, 3]
# 新しくイテレータを作成
iterator1 = iter(numbers)
iterator2 = iter(numbers)
print(list(iterator1)) # [1, 2, 3]
print(list(iterator2)) # [1, 2, 3]
ポイント
- リストなどのイテラブルは再利用可能だが、イテレータは1回のみ使用可能
- 再利用したい場合は、新しく
iter()
を呼び出す
③ メモリ効率と遅延評価
イテレータやジェネレータを利用すると、メモリ消費を抑えつつデータを処理できます。
例えば、リストとジェネレータの違いを比較してみましょう。
# リストを使う(すべての要素をメモリに格納)
numbers_list = [x * 2 for x in range(1000000)] # 100万個の要素
# ジェネレータを使う(必要なときに要素を生成)
numbers_gen = (x * 2 for x in range(1000000))
print(sum(numbers_list)) # 計算後、リストがメモリに残る
print(sum(numbers_gen)) # メモリを節約しながら計算
ポイント
- リスト はすべての要素をメモリに格納するため、大量のデータ処理には向かない
- ジェネレータ は遅延評価されるため、必要なときにのみ要素を生成できる
7. よくある質問(FAQ)
最後に、Pythonのイテレータについてよくある質問をまとめました。
Q1. イテレータとジェネレータの違いは何ですか?
A:
- イテレータは
__iter__()
と__next__()
を実装するクラス - ジェネレータは
yield
を使うことで簡単にイテレータを作成できる - ジェネレータの方がコードがシンプルになりやすい
Q2. なぜ __iter__()
と __next__()
メソッドが必要なのですか?
A:
__iter__()
はfor
ループがイテレータを扱うために呼び出す__next__()
は次の要素を取得するために使われる- Pythonの
for
ループが内部的にiter()
とnext()
を利用しているため
Q3. イテレータを使うメリットは何ですか?
A:
- メモリ効率が良い(特に大量データ処理時)
- 遅延評価が可能(必要なデータのみ生成)
- データストリーム処理に最適(APIレスポンス、ファイル処理など)
Q4. イテレータを手動で作成する必要があるのはどんな場合ですか?
A:
- カスタムなデータ処理を行うとき(例: 特定の条件を満たすデータのみを取得)
- APIからのストリーミングデータ処理
- 無限ループ的なデータ生成
Q5. イテレータと for
ループの関係は何ですか?
A:
for
ループは内部的にiter()
を呼び出し、next()
でデータを取得しているfor
を使うとStopIteration
の例外処理を自動で行ってくれるため、エラーにならない
まとめ
本記事では、Pythonのイテレータについて、基本から応用までを詳しく解説しました。
重要なポイントを振り返ると…
✅ イテレータは、データを一つずつ取り出すオブジェクト
✅ __iter__()
と __next__()
を実装すれば独自イテレータを作成できる
✅ ジェネレータを使えば、より簡単にイテレータを作成できる
✅ メモリ効率を向上させるために、イテレータは遅延評価を活用する
✅ APIレスポンスやストリームデータ処理、ファイル処理などで特に有用
Pythonのイテレータを活用することで、より効率的なデータ処理が可能 になります。ぜひ、実際にコードを試しながら理解を深めてみてください!