2 引数の iter() を使ってみる修行

イテレータを作る関数 iter() はシーケンスやイテレータを引数に渡すことになっている。だけどもうひとつ、実行可能なオブジェクトと番兵を渡す 2 引数のバージョンもあるようだ。ということで、使ってみた。

import random

class Kissa(object):
    def __call__(self):
        return random.randint(0, 9)

    def __getitem__(self, key):
        if key > 5: raise IndexError
        return random.randint(0, 9)

    @classmethod
    def main(cls):
        k = cls()
        for i in range(0, 10): print [v for v in iter(k)]    # ... (1)
        for i in range(0, 10): print [v for v in iter(k, 0)] # ... (2)

__call__ メソッドを定義すると任意のオブジェクトは実行可能になる。ここでは 0 から 9 までの整数をランダムで返すことにした。で、このオブジェクト k を番兵 0 として呼び出すイテレータを作るのが iter(k, 0) (2)。ついでに、シーケンス型のプロトコルも実装 (__getitem__ メソッドを実装。適切なところで IndexError を投げる) して、1 引数の iter でも呼び出せるようにした (1)。
実行結果。

>>> import kissa
>>> kissa.Kissa.main()
[4, 0, 8, 5, 1, 8]
[7, 4, 3, 8, 2, 7]
[1, 3, 1, 3, 2, 1]
[5, 4, 5, 4, 2, 3]
[7, 2, 6, 2, 7, 8]
[6, 6, 8, 1, 9, 4]
[7, 5, 4, 0, 8, 3]
[1, 6, 0, 6, 7, 4]
[1, 9, 9, 3, 9, 7]
[3, 0, 4, 6, 7, 7]
[4, 1, 2, 5, 4, 4, 5, 2, 4, 5, 1]
[1, 3, 6, 5, 3, 8, 4]
[]
[7, 9, 7, 9, 7]
[2, 4, 9, 6, 6, 8, 5, 4, 5, 8, 1, 9, 4, 9, 7, 7, 3]
[6, 7, 7, 1, 5, 6, 4, 8, 4]
[1, 7, 5]
[2, 5, 3, 6, 6, 9, 9, 5, 3, 4, 8, 8, 2, 2, 2, 1, 5]
[6, 1, 8, 9, 4, 2]
[6, 7, 2, 3, 8]

なるほど。