クラスを使ってカスタムイテレータを作ると、複雑な状態管理やカスタムロジックを持つイテレータを実装できます。ここでは実践的な例をいくつか紹介します。
範囲イテレータ
Python の range() のような機能を持つイテレータを作ってみましょう。
class MyRange: def __init__(self, start, stop, step=1): self.start = start self.stop = stop self.step = step def __iter__(self): current = self.start while current < self.stop: yield current current += self.step for n in MyRange(0, 10, 2): print(n, end=" ") # 0 2 4 6 8
逆順イテレータ
リストを逆順でイテレートするクラスです。
class Reversed: def __init__(self, data): self.data = data self.index = len(data) def __iter__(self): return self def __next__(self): if self.index == 0: raise StopIteration self.index -= 1 return self.data[self.index] for char in Reversed("hello"): print(char, end="") # olleh
サイクルイテレータ
要素を無限に繰り返すイテレータです。
class Cycle: def __init__(self, iterable): self.items = list(iterable) self.index = 0 def __iter__(self): return self def __next__(self): if not self.items: raise StopIteration item = self.items[self.index] self.index = (self.index + 1) % len(self.items) return item colors = Cycle(["red", "green", "blue"]) for i, color in enumerate(colors): if i >= 7: break print(color, end=" ") # red green blue red green blue red
ファイル行イテレータ
ファイルを特定の条件でフィルタリングしながら読み込むイテレータです。
class NonEmptyLines: def __init__(self, filename): self.filename = filename self.file = None def __iter__(self): self.file = open(self.filename, 'r') return self def __next__(self): while True: line = self.file.readline() if not line: self.file.close() raise StopIteration line = line.strip() if line: # 空行をスキップ return line # 使用例 # for line in NonEmptyLines("data.txt"): # print(line)
ペアイテレータ
隣り合う要素をペアで返すイテレータです。
class Pairwise: def __init__(self, iterable): self.iterator = iter(iterable) self.prev = None self.started = False def __iter__(self): return self def __next__(self): if not self.started: self.prev = next(self.iterator) self.started = True current = next(self.iterator) result = (self.prev, current) self.prev = current return result numbers = [1, 2, 3, 4, 5] for pair in Pairwise(numbers): print(pair) # (1, 2) # (2, 3) # (3, 4) # (4, 5)
設計のポイント
状態管理
インスタンス変数で現在位置や状態を管理する。__next__() で状態を更新する。
再利用性
同じオブジェクトを複数回イテレートしたい場合は、__iter__() で新しいイテレータを返す設計にする。
クラスベースのイテレータは柔軟性が高いですが、シンプルなケースではジェネレータ関数を使う方が簡潔です。