Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Pythonのitertools.productについて

Pythonのfor文が簡単に作れるitertoolsモジュールついて。itertools.productの基本的な使い方と考え方の解説

Pythonのループ処理が簡単に作れるitertoolsモジュールについて、特にitertools.productの基本的な使い方などを解説

Pythonにはループ処理を司るfor文やwhile文がありますが、そのループ処理を効率的に実行するためには上手くイテレータを作ることが重要です。

そんなイテレータを便利に作れるモジュールが用意されています。それがitertoolsというモジュールです。

このモジュールではいろいろな便利な関数が用意されていますが、今回はその例としてproduct関数の説明をします。これを使うと、多重for文(for文の中にfor文がある処理)を簡単に作ることができます。

itertools.productについて

itertools.productとは?

このproduct関数を使うとどうなるかというと、次のように説明されています。

入力イテラブルのデカルト積です。

ジェネレータ式の入れ子になった for ループとおよそ等価です。たとえば product(A, B) は ((x,y) for x in A for y in B) と同じものを返します。

Python公式ドキュメント

デカルト積というのはまぁ普通の掛け算だと思ってください。

とにかく多重for(入れ子になったfor)を簡単に書ける機能を提供しているという話です。

また大切なのは、itertoolsモジュールが提供する各関数を使うと、できあがるのはイテレータオブジェクト(以下イテレータ)だということです。イテレータを作って返します。

次に使い方は、

itertools.product(*iterables, repeat=1)

と書かれています。引数としては次の2種類です。

引数内容
*iterables1つ以上のイテラブルオブジェクト
repeatループの回数

このうち、「*iterables」のように、変数名に「*」がついた場合の意味については次の解説記事「Pythonの引数*args, **kwargsとは?その解説」を読んでください。

またイテラブルとイテレータの違いについては記事「【初心者にもわかりやすく】Pythonのイテレータについて、その基本とfor文の仕組みを解説」をご覧ください。形式的な説明にとどまる解説ではありますが、まずはその程度の説明で十分だと思います。

それではさっそくitertools.productの使用例を見ていきましょう。

コード例その1

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通りというとです。

コード例2

では次に、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がオススメです。セールで安く買える講座も多数!

愛を分かち合いましょう