PYTHON MEBY

Pythonでイテレータを実装(__iter__, __next__)

この記事では、Pythonでイテレータを実装する方法を説明します。`__iter__`メソッドと`__next__`メソッドの使い方、そして具体的な実装例を通して理解を深めます。

目次

イテレータとは?

イテレータは、反復可能なオブジェクトです。`next()`関数を使って、順次要素を取り出すことができます。リストやタプルなどのシーケンス型もイテレータとして使用できますが、自分でイテレータクラスを作成することで、より柔軟な反復処理を実現できます。

イテレータプロトコルは、`__iter__`メソッドと`__next__`メソッドの2つの特殊メソッドによって定義されます。

イテレータは、一度すべての要素をメモリにロードする必要がないため、巨大なデータセットを処理する際に効率的です。要素は必要になった時にのみ生成されます。

__iter__メソッド

イテレータオブジェクト自身を返します。これは、`for`ループなどがイテレータを使用する際に必要になります。

class MyIterator:
    def __iter__(self):
        return self

多くの場合、`__iter__`メソッドは`self`を返しますが、必要に応じて別のイテレータオブジェクトを返すことも可能です。

__next__メソッド

イテレータの次の要素を返します。要素がなくなったら`StopIteration`例外を送出します。

class MyIterator:
    def __next__(self):
        # ここに次の要素を生成するロジックを書く
        pass

`__next__`メソッドは、イテレータの心臓部です。ここで、イテレータが生成する要素を決定します。

実装例:数字の列挙

0から指定された数までを列挙するイテレータを実装してみましょう。

class NumberIterator:
    def __init__(self, limit):
        self.limit = limit
        self.current = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.limit:
            result = self.current
            self.current += 1
            return result
        else:
            raise StopIteration

for i in NumberIterator(5):
    print(i) # 出力: 0 1 2 3 4

この例では、`__next__`メソッドで`self.current`をインクリメントすることで、次の数を生成しています。`self.current`が`limit`を超えたら`StopIteration`例外を送出してループを終了します。

実装例:ファイルの行読み込み

ファイルから一行ずつ読み込むイテレータを実装します。

class FileIterator:
    def __init__(self, filepath):
        self.file = open(filepath, 'r')

    def __iter__(self):
        return self

    def __next__(self):
        line = self.file.readline()
        if line:
            return line.strip() # 改行コードを除去
        else:
            self.file.close()
            raise StopIteration

# 使用例(test.txtファイルが存在することを仮定)
filepath = 'test.txt'
with open(filepath, 'w') as f:
    f.write('line1\nline2\nline3')

for line in FileIterator(filepath):
    print(line) # 出力: line1 line2 line3

ファイルの読み込みは`readline()`メソッドで行います。ファイルの最後まで行くと空文字列が返されるため、それを`StopIteration`例外を送出する条件としています。`with`文を使用することで、ファイルが確実に閉じられるようにしています。

StopIteration例外

イテレータの要素がなくなったら、`StopIteration`例外を送出する必要があります。これにより、`for`ループや`next()`関数が正しく終了します。`StopIteration`例外を明示的に処理しない場合、例外が発生してプログラムが中断します。

関連記事