Pythonの循環器itertools

4941 ワード

ループオブジェクトと関数オブジェクトでは、ループの機能について説明します.ループはオブジェクトのコンテナで、複数のオブジェクトが含まれています.ループを呼び出すnext()メソッド(_next_()メソッドにより、Python 3.x)では、ループがオブジェクトを順次返します.すべてのオブジェクトが尽きるまで、ループはStopIterationエラーを挙げます.
 
for i in iterator構造では、ループが終了するまで、ループが戻るたびにオブジェクトがiに与えられます.iter()内蔵関数を使用すると、テーブルや辞書などのコンテナをループに変えることができます.たとえば
for i in iter([2, 4, 5, 6]):    
    print(i)

標準ライブラリのitertoolsパッケージは、ループをより柔軟に生成するツールを提供します.これらのツールの入力の多くは既存のループです.一方、これらのツールは完全に自分でPythonを使用して実現することができ、このパッケージは比較的標準的で効率的な実現方法を提供しているだけです.これもPythonの「解決策だけが望ましい」という理念に合っている.
# import the tools
from itertools import *

むげんじゅんかんき
count(5, 2)     # 5        ,    2, 5, 7, 9, 11, 13, 15 ...
cycle('abc')    #       , a, b, c, a, b, c ...
repeat(1.2)     #  1.2,       , 1.2, 1.2, 1.2, ...
 
repeat          :
repeat(10, 5)   #  10,   5 

関数ツール
関数式プログラミングは,関数自体を処理対象とするプログラミングパターンである.Pythonでは、関数もオブジェクトなので、map()、filter()、reduce()関数などの関数式の処理を簡単に行うことができます.
itertoolsには似たようなツールが含まれています.これらの関数はパラメータとして関数を受信し、結果をループに返します.
from itertools import *
rlt = imap(pow, [1, 2, 3], [1, 2, 3])
for num in rlt:    
    print(num)
imap()map()の違いは、imap()が無限配列に作用し、両配列の長さが一致しない場合、短いものに準じることである.
>>> for x in itertools.imap(lambda x, y: x * y, [10, 20, 30], itertools.count(0)):
...     print x
...
0
40
90

imap関数が表示されます.この関数はmap()関数の機能と似ていますが、シーケンスではなくループを返します.要素1,4,27,すなわち1*1,2*2,3*3の結果を含む.関数pow(組み込まれた乗方関数)を最初のパラメータとして使用します.pow()は,後の2つのリストの各要素に順次作用し,関数結果を収集し,返されるループを構成する.
また、次の関数も使用できます.
starmap(pow, [(1, 1), (2, 2), (3, 3)])
powは、テーブルの各tupleに順次作用します.
ifilter関数はfilter()関数と似ていますが、ループを返します.
ifilter(lambda x: x > 5, [2, 3, 5, 6, 7]

各要素にlambda関数を順次適用し、関数がTrueを返すと元の要素が収集されます.6, 7
また、
ifilterfalse(lambda x: x > 5, [2, 3, 5, 6, 7])
上と似ていますが、Falseを返す要素を収集します.2, 3, 5
 
takewhile(lambda x: x < 5, [1, 3, 6, 7, 1])
関数が偽を返すと、反復シーケンスではありません.1, 3
 
dropwhile(lambda x: x < 5, [1, 3, 6, 7, 1])
関数が偽を返すと、反復シーケンスが開始されます.6, 7, 1
コンビネーションツール
既存のループを組み合わせることで,新しいループを得ることができる.
chain([1,2,3],[4,5,7])#は2つのループを接続して1つになる.1, 2, 3, 4, 5, 7
for i in chain(dropwhile(lambda s:s>2,[1,2,3,4,5]),takewhile(lambda s:s>3,[4,5,1,2,3,4,5])):
    print i
1
2
3
4
5
4
5

product([1,2],[1,2])#複数のループセットのデカルト積.ネストされたループに相当
>>> for m, n in product([1,2], [1, 2]):   
...     print m,n
... 
1 1
1 2
2 1
2 2

permutations('abc',2)#abcd'からab,bcなどの2つの要素を選択します.すべての結果を並べ替えて、新しいループに戻ります.
なお、上記の組合せの順序、すなわちab,baはいずれも返される.
>>> for i in permutations('abc', 2) :
...     print i
... 
('a', 'b')
('a', 'c')
('b', 'a')
('b', 'c')
('c', 'a')
('c', 'b')

combinations('abc',2)#abcd'からab,bcなどの2つの要素を選択します.すべての結果を並べ替えて、新しいループに戻ります.
なお,上記の組合せは順序,すなわちab,baを問わず,1つのabのみを返す.
 
>>> for i in combinations('abc', 2) :
...     print i
... 
('a', 'b')
('a', 'c')
('b', 'c')

combinations_with_replacement('abc',2)#は上記と似ていますが、選択した要素を2回繰り返すことができます.すなわちaa,bb,ccが多くなった
groupby()
key関数を元のループの各要素に作用します.key関数の結果に基づいて、同じ関数の結果を持つ要素を新しいループに分けます.各新しいループは、関数の結果をラベルとして返します.
これはまるで人の身長が循環器として使われているようだ.身長が180より大きい場合は「tall」を返すkey関数を使用できます.身長が160以下なら「short」に戻る.中間のは「middle」を返します.最終的に、すべての身長は3つの循環器、すなわち「tall」、「short」、「middle」に分けられる.
>>> def height_class(h):
...     if h > 180:
...         return "tall"
...     elif h < 160:
...         return "short"
...     else:
...         return "middle"
... 
>>> friends = [191, 158, 159, 165, 170, 177, 181, 182, 190]
>>> friends = sorted(friends, key = height_class)
>>> friends 
[165, 170, 177, 158, 159, 191, 181, 182, 190]
>>> for m, n in groupby(friends, key = height_class):
...     print(m)
...     print(list(n))
... 
middle
[165, 170, 177]
short
[158, 159]
tall
[191, 181, 182, 190]

なおgroupbyの機能は、UNIXのuniqコマンドと同様である.グループ化する前にsorted()を使用して元のループの要素をソートし、key関数に基づいて並べ替え、同じグループの要素を先に位置に近づける必要があります.
            
friends = [191, 158, 159, 165, 170, 177, 181, 182, 190]
>>> for m, n in groupby(friends, key = height_class):
...     print(m)
...     print(list(n))
... 
tall
[191]
short
[158, 159]
middle
[165, 170, 177]
tall
[181, 182, 190]

その他のツール
compress('ABCD',[1,1,1,0])#は、[1,1,1,0]の真偽値の場合に基づいて、最初のパラメータ'ABCD'の要素を選択します.A, B, C
islice()はslice()関数に似ていますが、ループを返します.
izip()はzip()関数に似ていますが、ループを返します.
まとめ
itertoolsのツールはすべて自分で実現することができます.itertoolsは、より成形されたソリューションを提供するだけです.