今回は、Pythonのitertoolsモジュールの使い方を紹介します。
このモジュールは、さまざまなタスクに適したさまざまなタイプのイテレータを作成したい場合に非常に便利です。
このモジュールのメソッドのいくつかを学ぶことができれば、あなたのツールボックスにとても便利なものを追加することができます。
では早速、いくつかの便利なメソッドを見ていきましょう。
この記事もチェック:Pythonのstatisticsモジュールで便利なメソッドを7つ紹介する
Python Itertools – 役に立つメソッド
このセクションでは、イテレータを生成するいくつかの便利なメソッドについて見ていきます。
このモジュールを使うには、まずインポートする必要があります。
これは標準ライブラリにすでに含まれているので、プリインストールされていますよ。
import itertools
|
Python itertools.chain() を使ってイテレータブルを連結する
Python の itertools.chain()
メソッドは、複数のイテレータブルからイテレータを生成します。
これは単純に、すべてのイテレータブルを1つのシーケンスに連結し、その連結されたシーケンスへの単一のイテレータを返します。
このメソッドのシンタックスは以下のとおりです。
iterator = itertools.chain( * sequence)
|
これを理解するために、簡単な例を見てみましょう。
import itertools
list1 = [ 'hello' , 'from' , 'Python' ]
list2 = [ 10 , 20 , 30 , 40 , 50 ]
dict1 = { 'site' : 'Python' , 'url' : 'https://askpython.com' }
# We can combine lists and dicts (iterables) into a single chain for item in itertools.chain(list1, list2, dict1):
print (item)
|
ここでは、イテレータを直接使って、for item in ...
を使ってイテレータを反復しています。
結果は以下の通りです。
hello from Python 10 20 30 40 50 site url |
ここでは、リストの内容は正しく表示されますが、辞書の値は表示されません。
これを解決するには、 dict.items()
を使って (key, value)
ペアのタプルを取得すればよいでしょう。
import itertools
list1 = [ 'hello' , 'from' , 'Python' ]
list2 = [ 10 , 20 , 30 , 40 , 50 ]
dict1 = { 'site' : 'Python' , 'url' : 'https://askpython.com' }
# We can combine lists and dicts (iterables) into a single chain for item in itertools.chain(list1, list2, dict1.items()):
print (item)
|
結果は以下の通りです。
hello from Python 10 20 30 40 50 ('site', 'Python') ('url', 'https://askpython.com') |
確かに、イテラブルとして dict1.items()
を使用することで、値も表示されるようになりました!
Python itertools.count() を使ってカウンタベースのシーケンスを生成する
Python の関数 itertools.count()
を使って、カウントに対応するイテレータを作成することができます。
iterator = itertools.count(start = 0 , step = 1 )
|
ここで、これは0から無限にカウントし続けるイテレータです。
これは、step=1
ずつカウントを増やし続ける。
また、これを10進数/負数に設定することもできる。
例えば、無限ループがあることを証明したい場合、以下のスニペットを実行することができますが、これは推奨されません。
ただし、itertools.count()
が無限にカウントすることが理解できることを確認してください。
for num in itertools.count(start = 0 , step = 1 ):
# Infinite loop!
print (num)
|
さて、この関数の使い方はすぐにはわからないかもしれませんが、zip メソッドなどの他の関数と組み合わせてシーケンスを構成することができます。
次のような例を考えてみましょう。
import itertools
numbers = [ 100 , 200 , 300 , 400 ]
data = list ( zip (itertools.count( 0 , 10 ), numbers))
print (data)
|
ここで、イテレータの威力を実感してください。
さて、これはリスト内のアイテムのインデックスを作成するために使用されます。
[( 0 , 100 ), ( 10 , 200 ), ( 20 , 300 ), ( 30 , 400 )]
|
さて、Pythonの itertools.count()
を使ってイテレータ列のサブセットを得たい場合、 itertools.islice()
を使ってイテレータのスライスだけを構築することもできます。
import itertools
for num in itertools.islice(itertools.count(start = 0 , step = 10 ), 4 ):
print (num)
for num in itertools.islice(itertools.count(), 0 , 50 , 10 ):
print (num)
|
結果は以下の通りです。
0 10 20 30 0 10 20 30 40 |
見ての通り、どちらの配列も同じです。
解決すべき問題に応じて、適切な方法を選択してください。
itertools.repeat() を使って値を繰り返す
ある特定の値を繰り返したい場合、 itertools.repeat(value)
を使って繰り返される値のイテレータを構築することができます。
例えば、(i, 5)
という形のシーケンスを作りたい場合、i は 0 から 10 までの範囲であるため、この関数を使うことができます!
import itertools
data = list ( zip ( range ( 10 ), itertools.repeat( 5 )))
print (data)
|
結果は以下の通りです。
[(0, 5), (1, 5),
(2, 5),
(3, 5),
(4, 5),
(5, 5),
(6, 5),
(7, 5),
(8, 5),
(9, 5)]
|
確かに、この数列は簡単に作れましたね。
この関数が役に立つもう一つの例は、Pythonのmap()を使って正方形を作ろうとする場合です。
squares = list ( map ( pow , range ( 10 ), itertools.repeat( 2 )))
print (squares)
|
結果は以下の通りです。
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81] |
map()` を使って簡単に作図できたのがわかるでしょうか?
itertools.tee() による配列のクローン作成
配列をクローンして、2つの配列を生成する tee()
という便利な関数もあります。
cloned1, cloned2 = itertools.tee(original_sequence)
|
これは、Linux の tee コマンドが出力のクローンを作成することを元にしています。
ここで、tee()
を使って配列を複製した場合、同じイテレータを再び使用することはできません。
そのため、この関数を使用する際には十分な注意が必要です。
import itertools
single_iterator = itertools.islice(itertools.count(), 3 )
cloned1, cloned2 = itertools.tee(single_iterator)
for num in cloned1:
print ( 'cloned1: {}' . format (num))
for num in cloned2:
print ( 'cloned2: {}' . format (num))
|
結果は以下の通りです。
cloned1: 0 cloned1: 1 cloned1: 2 cloned2: 0 cloned2: 1 cloned2: 2 |
確かに、クローンされた2つの配列が同じ出力を持つことがわかります。
itertools.cycle() を使ってシーケンスを循環させる
itertools.cycle()` 関数は、無限に循環させることができるイテレータを提供します!
これは、アプリケーションの中で状態を切り替え続けたい場合に便利です。
電球の2つの状態を考えてみましょう。
「オン “と “オフ “です。
スイッチが押されるたびにこの 2 つの状態を繰り返すイテレータを作成することができます!
import itertools
# Initially, bulb is switched off, so off is the first element in the list bulb_states = itertools.cycle([ "off" , "on" ])
for _ in range ( 5 ):
# Use next(iterator) to get the current state
curr_state = next (bulb_states)
print (f "Bulb state currently {curr_state}" )
|
結果は以下の通りです。
Bulb state currently off Bulb state currently on Bulb state currently off Bulb state currently on Bulb state currently off |
確かに、電球の状態は「オン」と「オフ」の2つの値の間を循環し続けますね
takewhile() と dropwhile() を使ったアイテムのフィルタリング
Python の itertools.takewhile()
関数を使用すると、ある条件が True
である限りシーケンスアイテムをフィルタリングすることができます。
もし、条件が False
になったら、フィルタリングを停止します。
iterator = itertools.takewhile(condition, * sequence)
|
以下は、数字が正である限り、数字をフィルタリングする簡単な例です。
import itertools
sequence = itertools.takewhile( lambda x: x > 0 , [ 1 , 2 , 3 , - 1 , 10 ])
for item in sequence:
print (item)
|
結果は以下の通りです。
1 2 3 |
ここでは、次の要素が -1 であるため、シーケンスは 3 の後で停止しています。
同様に、 itertools.dropwhile()
は、条件が False
である限り要素をフィルタリングし、最初の偽でない値以降のすべての要素を返します。
import itertools
data = itertools.dropwhile( lambda x: x < 5 , [ 3 , 12 , 7 , 1 , - 5 ])
for item in data:
print (item)
|
結果は以下の通りです。
12 7 1 -5 |
combinations()を使って組み合わせを作成します。
Python の itertools.combinations()
を使っても、組み合わせシーケンスを作成することができます。
iterator = itertools.combinations( * sequence, r)
|
以下は簡単な例です。
import itertools
words = [ 'hello' , 'from' , 'Python' , 'how' ]
results = itertools.combinations(words, 2 )
for item in results:
print (item)
|
結果は以下の通りです。
('hello', 'from') ('hello', 'Python') ('hello', 'how') ('from', 'Python') ('from', 'how') ('Python', 'how') |
組合せの中に連続した要素の繰り返しを持たせたい場合は、 combinations_with_replacement()
を使うことができる。
results = itertools.combinations_with_replacement(words, 3 )
for item in results:
print (item)
|
結果は以下の通りです。
('hello', 'hello', 'hello') ('hello', 'hello', 'from') ('hello', 'hello', 'Python') ('hello', 'hello', 'how') ('hello', 'from', 'from') ('hello', 'from', 'Python') ('hello', 'from', 'how') ('hello', 'Python', 'Python') ('hello', 'Python', 'how') ('hello', 'how', 'how') ('from', 'from', 'from') ('from', 'from', 'Python') ('from', 'from', 'how') ('from', 'Python', 'Python') ('from', 'Python', 'how') ('from', 'how', 'how') ('Python', 'Python', 'Python') ('Python', 'Python', 'how') ('Python', 'how', 'how') ('how', 'how', 'how') |
同様に、permutations()
と permutations_with_replacement()
を使って並べ替えをリストアップすることができます。
以上で、このモジュールの重要な関数のいくつかを終了します。
より多くの関数については、公式のドキュメントを参照してください。
まとめ
この記事では、Pythonの itertools
モジュールの様々な関数について見てきました。