Iteratorパターン

概要

各要素に順番にアクセスする」パターンです。

Pythonはビルトインの形でIteratorをサポートしています。

例えば、リストをfor文に渡すと変数に代入してくれるのも、Iteratorをサポートしているからです。

l = [1, 2, 3]

for i in l:
    print(i)

以下の例では、PythonのIteratorについていくつか紹介をします。

例題

Iteratorを自作します
シンプルに、10, 20, 30という3つの数字を順番に出力するHogeクラスを作成します。

サンプルコード

def main():
    my_iterator = Hoge(10, 20, 30)
    for num in my_iterator:
        print(num)


class Hoge:

    def __init__(self, *numbers):
        self._numbers = numbers
        self._i = 0

    def __iter__(self):
        print("__iter__ is called")
        return self
        # return "hoge" # => TypeError: iter() returned non-iterator of type 'str'

    def __next__(self):
        print("__next__ is called")
        if self._i == len(self._numbers):
            raise StopIteration()
        value = self._numbers[self._i]
        self._i += 1
        return value


if __name__ == "__main__":
    main()

参考

# 出力

__iter__ is called __next__ is called 10 __next__ is called 20 __next__ is called 30 __next__ is called

特徴

あるオブジェクトがイテレータを期待するコンテクストに置かれると、
(例:for i in object: となると)

  • __iter__ メソッドが呼ばれる
  • イテレート(繰り返し)するたびに__next__メソッドが呼ばれる
  • StopIteration()をraiseすると繰り返しが止まる

上記3つの処理が走ります。
したがって、上のようなコードを書くと、本来のfor文の挙動を再現することができます。

Pythonらしく書くためのコツ

Pythonのビルトイン機能を使うことで特に意識することなくIteratorを使用できます。

クラス図

# 一般的なクラス図

一般的なクラス図(Iteratorパターン)

# サンプルコードにおけるクラス図

特になし

参考URL

実践Python3

Pythonのイテレータとジェネレータ