Pythonのイテレータとイテラブルとは?
Python
におけるイテレータ(iterator)とイテラブル(iterable)は、繰り返し処理を支える重要な概念です。これらは、Python
のfor
ループや他の繰り返し構文の基礎を形成しています。例えば、リストやタプル、辞書、文字列などは、すべてイテラブルと呼ばれます。これらのイテラブルオブジェクトから要素を順に取り出すための仕組みが、イテレータです。
この記事では、イテレータとイテラブルの違い、仕組み、実際の使い方、カスタムイテレータの作り方を解説します。
イテラブルとは?
イテラブル(iterable)は、for
ループや他の繰り返し処理で使用できるオブジェクトのことです。イテラブルオブジェクトには、リスト、タプル、文字列、辞書、セットなどが含まれます。これらは、内部的に__iter__()
というメソッドを持っており、このメソッドがイテレータを返します。
イテラブルの例
my_list = [1, 2, 3, 4, 5]
# リストはイテラブル
for item in my_list:
print(item)
このように、for
ループを使ってリストの各要素を繰り返し処理できるのは、リストがイテラブルだからです。for
ループを使うと、Python
は内部的にmy_list.__iter__()
を呼び出し、イテレータを生成しています。
イテラブルの確認方法
イテラブルかどうかを確認するには、iter()
関数を使います。iter()
が成功すれば、そのオブジェクトはイテラブルです。
my_tuple = (10, 20, 30)
my_iterable = iter(my_tuple)
print(my_iterable) # 出力: <tuple_iterator object at 0x...>
このコードでは、タプルがイテラブルであるため、iter()
関数を使ってイテレータを取得できます。
イテレータとは?
イテレータ(iterator)は、イテラブルから次の要素を順番に取り出すオブジェクトです。イテレータは、__iter__()
と__next__()
という2つのメソッドを実装しており、next()
関数を使うことで、1つずつ要素を取得できます。
イテレータの例
次に、イテレータの動作を確認してみましょう。
my_list = [1, 2, 3]
my_iterator = iter(my_list)
# イテレータから順に要素を取得
print(next(my_iterator)) # 出力: 1
print(next(my_iterator)) # 出力: 2
print(next(my_iterator)) # 出力: 3
# 要素がなくなるとStopIteration例外が発生
print(next(my_iterator)) # 出力: StopIteration
ここでは、iter()
関数でリストのイテレータを作成し、next()
関数で要素を順に取り出しています。すべての要素を取得し終わると、StopIteration
例外が発生します。
__next__()
と__iter__()
の役割
__iter__()
: イテレータオブジェクトそのものを返します。これにより、イテレータはイテラブルとしても機能します。__next__()
: イテレータの次の要素を返します。要素がなくなるとStopIteration
を発生させます。
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else:
raise StopIteration
# MyIteratorクラスの使用例
my_iter = MyIterator([10, 20, 30])
for item in my_iter:
print(item)
この例では、MyIterator
クラスがカスタムイテレータを定義しています。__next__()
メソッドでデータを1つずつ返し、要素が尽きるとStopIteration
を発生させています。
イテラブルとイテレータの違い
- イテラブル: 繰り返し処理ができるオブジェクト。リストやタプル、文字列など。
__iter__()
メソッドを持ち、このメソッドがイテレータを返す。 - イテレータ: 次の要素を返すオブジェクト。
__next__()
メソッドを持ち、要素がなくなるとStopIteration
を送出する。イテレータ自身もイテラブルであり、__iter__()
メソッドを持つ。
カスタムイテレータの作成
Python
では、自分でイテレータを作成することもできます。イテレータを作成するには、__iter__()
と__next__()
メソッドを実装します。
例:カスタムカウンタイテレータ
次に、特定の範囲で動作するカウンタを持つイテレータを実装してみましょう。
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:
result = self.current
self.current += 1
return result
else:
raise StopIteration
# カスタムカウンタの使用例
counter = Counter(1, 5)
for num in counter:
print(num)
このCounter
クラスは、start
からend
までの数値を順に返すイテレータです。__next__()
メソッドで次の値を返し、end
に達するとStopIteration
を送出します。
ジェネレータとイテレータの違い
イテレータと似た概念にジェネレータがあります。ジェネレータは、yield
文を使って値を返す特殊な関数で、実装が簡単なイテレータの一種です。
ジェネレータの例
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
for val in gen:
print(val)
ジェネレータは内部で自動的にイテレータとして動作し、yield
で次の値を返します。for
ループで使用すると、イテレータと同じように動作します。
イテレータとイテラブルの活用例
イテレータとイテラブルは、Python
での繰り返し処理を効率化する強力なツールです。これらは、大規模なデータセットの処理や、要素を一度にすべて読み込まずに処理する場面で特に役立ちます。
例:ファイルの行をイテレータで処理
with open('data.txt', 'r') as file:
for line in file:
print(line.strip())
ファイルオブジェクトはイテラブルなので、for
ループで1行ずつ処理できます。これにより、メモリ効率よく大きなファイルを扱うことが可能です。
結論
Python
のイテラブルとイテレータは、繰り返し処理の基盤となる重要な概念です。イテラブルは繰り返し可能なオブジェクトであり、for
ループで直接利用できます。一方、イテレータはnext()
関数で要素を1つずつ取得できるオブジェクトです。
イテレータは、カスタムクラスやデータストリームなどで活用することで、大量のデータ処理や動的なデータ生成に役立ちます。イテラブルとイテレータの仕組みを理解し、適切に使うことで、効率的なPython
プログラムを作成することができるでしょう。