6.5.1 Itertool関数

以下の関数は全て、イテレータを作成して返します。無限長のストリームのイテ レータを返す関数もあり、この場合にはストリームを中断するような関数かルー プ処理から使用しなければなりません。

chain( *iterables)
先頭のiterableの全要素を返し、次に2番目のiterableの全要素…と全 iterableの要素を返すイテレータを作成します。連続したシーケンスを、一つ のシーケンスとして扱う場合に使用します。この関数は以下のスクリプトと同 等です:

     def chain(*iterables):
         for it in iterables:
             for element in it:
                 yield element

count( [n])
nで始まる、連続した整数を返すイテレータを作成します。n を 指定しなかった場合、デフォルト値はゼロです。現在、 Pythonの長整数はサポートしていません。imap()で連続したデー タを生成する場合やizip()でシーケンスに番号を追加する場合な どに引数として使用することができます。この関数は以下のスクリプトと同等 です:

     def count(n=0):
         while True:
             yield n
             n += 1

count()はオーバーフローのチェックを行いません。このため、 sys.maxintを超えると負の値を返します。この動作は将来変更されま す。

cycle( iterable)
iterableから要素を取得し、同時にそのコピーを保存するイテレータを作成し ます。iterableの全要素を返すと、セーブされたコピーから要素を返し、これ を無限に繰り返します。この関数は以下のスクリプトと同等です:

     def cycle(iterable):
         saved = []
         for element in iterable:
             yield element
             saved.append(element)
         while saved:
             for element in saved:
                   yield element

cycleは大きなメモリ領域を使用し ます。使用するメモリ量はiterableの大きさに依存します。

dropwhile( predicate, iterable)
predicateが真である限りは要素を無視し、その後は全ての要素を返すイテ レータを作成します。このイテレータは、predicateが真の間は全く要 素を返さないため、最初の要素を返すまでに長い時間がかかる場合がありま す。この関数は以下のスクリプトと同等です:

     def dropwhile(predicate, iterable):
         iterable = iter(iterable)
         for x in iterable:
             if not predicate(x):
                 yield x
                 break
         for x in iterable:
             yield x

groupby( iterable[, key])
同じキーをもつような要素からなるiterable 中のグループに対して、 キーとグループを返すようなイテレータを作成します。 key は各要素に対するキー値を計算する関数です。キーを指定しない 場合や None にした場合、key 関数のデフォルトは恒等関数になり 要素をそのまま返します。通常、iterable は 同じキー関数で並べ替え済みである必要があります。

返されるグループはそれ自体がイテレータで、groupby()iterable を共有しています。もととなるiterable を 共有しているため、groupby オブジェクトの要素取り出しを 先に進めると、それ以前の要素であるグループは見えなくなってしまいます。 従って、データが後で必要な場合にはリストの形で保存しておく必要があります:

    groups = []
    uniquekeys = []
    for k, g in groupby(data, keyfunc):
        groups.append(list(g))      # Store group iterator as a list
        uniquekeys.append(k)

groupby() は以下のコードと等価です:

    class groupby(object):
        def __init__(self, iterable, key=None):
            if key is None:
                key = lambda x: x
            self.keyfunc = key
            self.it = iter(iterable)
            self.tgtkey = self.currkey = self.currvalue = xrange(0)
        def __iter__(self):
            return self
        def next(self):
            while self.currkey == self.tgtkey:
                self.currvalue = self.it.next() # Exit on StopIteration
                self.currkey = self.keyfunc(self.currvalue)
            self.tgtkey = self.currkey
            return (self.currkey, self._grouper(self.tgtkey))
        def _grouper(self, tgtkey):
            while self.currkey == tgtkey:
                yield self.currvalue
                self.currvalue = self.it.next() # Exit on StopIteration
                self.currkey = self.keyfunc(self.currvalue)
バージョン 2.4 で 新たに追加 された仕様です。

ifilter( predicate, iterable)
predicateがTrueとなる要素だけを返すイテレータを作成します。 predicateNoneの場合、値が真であるアイテムだけを返しま す。この関数は以下のスクリプトと同等です:

     def ifilter(predicate, iterable):
         if predicate is None:
             predicate = bool
         for x in iterable:
             if predicate(x):
                 yield x

ifilterfalse( predicate, iterable)
predicateがFalseとなる要素だけを返すイテレータを作成します。 predicateNoneの場合、値が偽であるアイテムだけを返しま す。この関数は以下のスクリプトと同等です:

     def ifilterfalse(predicate, iterable):
         if predicate is None:
             predicate = bool
         for x in iterable:
             if not predicate(x):
                 yield x

imap( function, *iterables)
iterablesの要素を引数としてfuntionを呼び出すイテレータを作成します。 functionNoneの場合、引数のタプルを返します。 map()と似ていますが、最短のiterableの末尾まで到達した後は Noneを補って処理を続行するのではなく、終了します。これは、 map()に無限長のイテレータを指定するのは多くの場合誤りですが (全出力が評価されてしまうため)、imap()の場合には一般的で役 に立つ方法であるためです。この関数は以下のスクリプトと同等です:

     def imap(function, *iterables):
         iterables = map(iter, iterables)
         while True:
             args = [i.next() for i in iterables]
             if function is None:
                 yield tuple(args)
             else:
                 yield function(*args)

islice( iterable, [start,] stop [, step])
iterableから要素を選択して返すイテレータを作成します。startが0以 外であれば、iterableの先頭要素はstartに達するまでスキップします。以 降、stepが1以下なら連続した要素を返し、1以上なら指定された値分の 要素をスキップします。stopNoneであれば、無限に、もしく はiterableの全要素を返すまで値を返します。None以外ならイテレー タは指定された要素位置で停止します。通常のスライスと異なり、 startstopstepに負の値を指定する事はできません。 シーケンス化されたデータから関連するデータを取得する場合(複数行からなるレ ポートで、三行ごとに名前が指定されている場合など)に使用します。この関 数は以下のスクリプトと同等です:
     def islice(iterable, *args):
         s = slice(*args)
         it = iter(xrange(s.start or 0, s.stop or sys.maxint, s.step or 1))
         nexti = it.next()
         for i, element in enumerate(iterable):
             if i == nexti:
                 yield element
                 nexti = it.next()

startNoneならば、繰返しは0から始まります。 stepNoneならば、ステップは1となります。 バージョン 2.5 で 変更 された仕様: startstepはデフォルト値として Noneを受け付けます。

izip( *iterables)
各iterableの要素をまとめるイテレータを作成します。zip()に似 ていますが、リストではなくイテレータを返します。複数のイテレート可能オ ブジェクトに対して、同じ繰り返し処理を同時に行う場合に使用します。この 関数は以下のスクリプトと同等です:

     def izip(*iterables):
         iterables = map(iter, iterables)
         while iterables:
             result = [it.next() for it in iterables]
             yield tuple(result)

バージョン 2.4 で 変更 された仕様: イテレート可能オブジェクトを指定しない場合、 TypeError例外を送出する代わりに長さゼロのイテレータを返し ます。

イテレート可能オブジェクトの左から右への評価順序は保証されることに注意 して下さい。このことによって、データ列を長さnのグループにまとめる常套 句 "izip(*[iter(s)]*n)" が実現可能になります。長さnのグループにま とめるのに中途半端なデータ列に対しては "izip(*[chain(s, [None]*(n-1))]*n)" のように、最後のタプルを埋める値をあらかじめ準備し ておくことができます。

もう一つの注意は izip() が長さが不揃いの入力に対して呼ばれた 時、izip() 終了の後引き続いて長い方のイテレート可能オブジェ クトを呼び出した結果は保証の限りではないということです。可能性として、 残ったそれぞれのイテレート可能オブジェクトから値が一つ失われているかも しれないし失われていないかもしれません。これは次のようにして起こります。 実行中にそれぞれのイテレート可能オブジェクトから一つずつ値を取り出しま すが、その処理がいずれかのイテレート可能オブジェクトが空になることによ り終了します。この時途中まで取り出された値たちは宙に浮きます(不完全なタ プルとして送り出されることもなく、また次の it.next() のためにイ テレート可能オブジェクトに押し戻すこともできません)。一般に、 izip() を長さが不揃いな入力に使うのは、残され使われなかった 長い方のイテレート可能オブジェクトの値を気にしない時だけにするべきです。

repeat( object[, times])
繰り返しobjectを返すイテレータを作成します。timesを指定し ない場合、無限に値を返し続けます。imap()で常に同じオブジェク トを関数の引数として指定する場合に使用します。また、izip() で作成するタプルの全要素に常に同じオブジェクトを指定する場合にも使用す ることもできます。この関数は以下のスクリプトと同等です:

     def repeat(object, times=None):
         if times is None:
             while True:
                 yield object
         else:
             for i in xrange(times):
                 yield object

starmap( function, iterable)
iterablesの要素を引数としてfuntionを呼び出すイテレータを作成します。 functionの引数が単一のiterableにタプルとして格納されている場合(``zip済 み'')、imap()の代わりに使用します。imap()starmap()ではfunctionの呼び出し方法が異なり、 imap()function(a,b)starmap()では function(*c)のように呼び出します。この関数は以下のスクリプトと 同等です:

     def starmap(function, iterable):
         iterable = iter(iterable)
         while True:
             yield function(*iterable.next())

takewhile( predicate, iterable)
predicateが真である限りiterableから要素を返すイテレータを作成します。 この関数は以下のスクリプトと同等です:

     def takewhile(predicate, iterable):
         for x in iterable:
             x = iterable.next()
             if predicate(x):
                 yield x
             else:
                 break

tee( iterable[, n=2])
一つのiterable からn 個の独立したイテレータを生成して 返します。n==2 の場合は、以下のコードと等価になります:

     def tee(iterable):
         def gen(next, data={}, cnt=[0]):
             for i in count():
                 if i == cnt[0]:
                     item = data[i] = next()
                     cnt[0] += 1
                 else:
                     item = data.pop(i)
                 yield item
         it = iter(iterable)
         return (gen(it.next), gen(it.next))

一度tee() でイテレータを分割すると、もとの iterable を他で使ってはならなくなるので注意してください; さもなければ、 tee オブジェクトの知らない間にiterable が先の要素に 進んでしまうことになります。

teeはかなり大きなメモリ領域を使用します (使用するメモリ量はiterableの大きさに依存します)。 一般には、一つのイテレータが他のイテレータよりも先に ほとんどまたは全ての要素を消費するような場合には、tee() よりもlist() を使った方が高速です。 バージョン 2.4 で 新たに追加 された仕様です。

ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。