Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
Pythonにはループ処理を司るfor文やwhile文がありますが、そのループ処理を効率的に実行するためには上手くイテレータを作ることが重要です。
そんなイテレータを便利に作れるモジュールが用意されています。それがitertoolsというモジュールです。
このモジュールではいろいろな便利な関数が用意されていますが、今回はその例としてproduct関数の説明をします。これを使うと、多重for文(for文の中にfor文がある処理)を簡単に作ることができます。
このproduct関数を使うとどうなるかというと、次のように説明されています。
入力イテラブルのデカルト積です。
ジェネレータ式の入れ子になった for ループとおよそ等価です。たとえば
Python公式ドキュメントproduct(A, B)
は((x,y) for x in A for y in B)
と同じものを返します。
デカルト積というのはまぁ普通の掛け算だと思ってください。
とにかく多重for(入れ子になったfor)を簡単に書ける機能を提供しているという話です。
また大切なのは、itertoolsモジュールが提供する各関数を使うと、できあがるのはイテレータオブジェクト(以下イテレータ)だということです。イテレータを作って返します。
次に使い方は、
itertools.product(*iterables, repeat=1)
と書かれています。引数としては次の2種類です。
引数 | 内容 |
---|---|
*iterables | 1つ以上のイテラブルオブジェクト |
repeat | ループの回数 |
このうち、「*iterables」のように、変数名に「*」がついた場合の意味については次の解説記事「Pythonの引数*args, **kwargsとは?その解説」を読んでください。
またイテラブルとイテレータの違いについては記事「【初心者にもわかりやすく】Pythonのイテレータについて、その基本とfor文の仕組みを解説」をご覧ください。形式的な説明にとどまる解説ではありますが、まずはその程度の説明で十分だと思います。
それではさっそくitertools.productの使用例を見ていきましょう。
import itertools
companies = ["Google", "Apple", "Amazon"]
nums = range(0, 2)
def test_itertools(*iterables, repeat_times):
# print(*iterables) # >>> ['Google', 'Apple', 'Amazon'] range(0, 2)
# print(iterables) # >>>(['Google', 'Apple', 'Amazon'], range(0, 2))
result_list = []
for i in itertools.product(*iterables, repeat=repeat_times):
result_list.append(i)
print(result_list)
print(len(result_list))
test_itertools(companies, nums, repeat_times=1)
test_itertools関数の実引数で、「repeat_times=1」と設定している点に注目してください。
この結果は、
[('Google', 0), ('Google', 1), ('Apple', 0), ('Apple', 1), ('Amazon', 0),('Amazon', 1)]
6
そして処理の流れの解説ですが、
test_itertoolsの実引数のうち、companiesとnumsが、その仮引数*itereblesに格納される
(# print(*iterables) # >>> ['Google', 'Apple', 'Amazon'] range(0, 2)で確認)
↓
itertools.product(イテラブルオブジェクトA, イテラブルオブジェクトB)は、((x,y) for x in A for y in B)と同じような仕組み。そして今回は、*iterableが展開されて、
・イテラブルオブジェクトA = comapnies
・イテラブルオブジェクトB = nums
となり、
[(x,y) for x in companies for y in nums]
(リスト内包表記を使用)
とだいたい同じ。
という感じですね。
次の画像を参考にしてください。会社名と数字の組み合わせ図です。
会社名が3つ、数字が2つの組み合わせで、3×2の6通りというとです。
では次に、test_itertoolsの実引数で「repeat_times=2」とした場合の結果を見てみましょう。次のようになります。
[('Google', 0, 'Google', 0), ('Google', 0, 'Google', 1), ('Google', 0, 'Apple', 0), ('Google', 0, 'Apple', 1),('Google', 0, 'Amazon', 0), ('Google', 0, 'Amazon', 1), ('Google', 1, 'Google', 0), ('Google', 1, 'Google',1), ('Google', 1, 'Apple', 0), ('Google', 1, 'Apple', 1), ('Google', 1, 'Amazon', 0), ('Google', 1, 'Amazon', 1),('Apple', 0, 'Google', 0), ('Apple',0, 'Google', 1), ('Apple', 0, 'Apple', 0), ('Apple', 0, 'Apple', 1), ('Apple', 0, 'Amazon', 0), ('Apple', 0, 'Amazon', 1), ('Apple', 1, 'Google', 0), ('Apple', 1, 'Google', 1), ('Apple', 1, 'Apple', 0), ('Apple', 1, 'Apple', 1), ('Apple', 1, 'Amazon', 0), ('Apple', 1, 'Amazon', 1), ('Amazon', 0, 'Google', 0), ('Amazon', 0, 'Google', 1), ('Amazon', 0, 'Apple', 0), ('Amazon', 0, 'Apple', 1), ('Amazon', 0,'Amazon', 0), ('Amazon', 0, 'Amazon', 1), ('Amazon', 1, 'Google', 0), ('Amazon', 1, 'Google', 1), ('Amazon', 1, 'Apple', 0), ('Amazon', 1, 'Apple',1), ('Amazon', 1, 'Amazon', 0), ('Amazon', 1, 'Amazon', 1)]
36
となります。
これも次の図を見て下さい。結果の一部だけですが、
コード例1の結果である「会社名と数字の組み合わせ」が2回繰り返されているのがわかるでしょうか。
上のコード例1の結果はこうでした。
これが、2つ繰り返されているという感じです。
それゆえ、repeat_times=1の場合は3×2でしたが、repeat_times=2とした場合は3x2x3x2=36通りとなります。6の「2乗」ということですね。
この場合、単純に考えるとfor文ろ4重の入れ子にすればいいのですが、そんなコード書きたくないですよね。深い階層構造となるループ処理はそれを作った本人が後で読んでも「??」となる可能性が高いですよね。
そんなときこのitertools.productを使うと可読性の高いコードが書けるというわけです。もちろん慣れは必要ですが。
以上product関数を例にしてましたが、このようにitertooslモジュールはPythonのループ処理を簡単に、便利に作れる様々な関数を提供してくれています。このproduct関数以外にもいろいろなものが用意されているので、ぜひ公式ドキュメントでチェックしてみてください。
最速でプログラミングをマスターするならTechAcademy [テックアカデミー] 【PR】がオススメです。
マイペースで学ぶなら世界最大級の動画学習サイトUdemyがオススメです。セールで安く買える講座も多数!