それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

Iteratorの定義

PyJUGの石本 敦夫さんのスライドをみた。PythonはなんでもかんでもIteratorにすることが可能。

スライドより、Iteratorを実装したオブジェクト作成例

class AIterator(object):
    """seq1,se2内の要素を交互に返すIterator"""
    def __init__( self, seq1,seq2 ):
        self._seqs = ( seq1, seq2 )
        self._cur = 0
        self._max = min( len(seq1), len(seq2) )#最大インデックス値
        
    def __iter__(self):
        return self
    
    def next(self):
        n,idx = self._cur %2 , self._cur //2
        if idx >= self._max:
            raise StopIteration #Iterate終了
        ret = self._seqs[n][idx]
        self._cur += 1
        return ret


for v in AIterator( range(10), range(100, 110) ):
    print v

注目するのは以下の三点

  • next()
    • raise StopIteration
  • __iter__()

これがIteratorの重要点。


for x in A: でLoopさせたいときは、次の関数を作っておく。

def next(self)       #繰り返しさせるオブジェクト(raise StopIterationする関数)
def __iter__(self)   #繰り返しさせるオブジェクトを返すメソッド(nextをもったオブジェクト)

の二つのメソッドがあればいい。

一般的には

  • Iteratable Object#繰り返し可能オブジェクト
  • Iterator Object#繰り返しオブジェクト

と呼ぶらしい。

実装例。File オブジェクトを見てみる

inFile = open("./foo.txt")
for line in inFile:
    print line

 __builtin__のリファレンスより

open(name[, mode[, buffering]]) -> file object

Open a file using the file() type, returns a file object.

fileのリファレンスより、__iter__とnextがある。

next :
      x.next() -> the next value, or raise StopIteration
__iter__:
      x.__iter__() <==> iter(x)

open の返す、file オブジェクトがiteratorable なオブジェクトでIteratorを返してくれる。


__iter__の返すオブジェクトがnextを持っていればいい。nextはStopIteration Exceptionをthrowする

これはSimpleで良いよね。


JavaのObject指向に近い言語だと、Interfaceを使う。Pythonには無いので、マニュアルに「これらの関数を作ってね」と書いてあるわけだ。Interfaceが無いと、チーム開発時に説明しにくいよね。

JavaのObject指向を取り入れた(と思う)PHP5でもInterfaceを使う

PHPだとSPLつかって実装する*1

key()
next()
seek()
valid()
rewind()
current()

のメソッドをimplemntsしなくちゃいけない。*2

*1:* オブジェクトをArrayとして使う場合

*2:だいぶ前に試したとき、next(),current()実装しただけで動いてたような