Python | データ構造強化:itertools.product

Python Python
スポンサーリンク

概要(product は「直積=すべての組み合わせ」を省メモリで生成する)

itertools.product は複数のイテラブル(リスト、文字列、range など)から「取りうるすべての組み合わせ(デカルト積)」を順に返すイテレータです。多重 for ループを1行にまとめられ、結果を一度にメモリへ載せないため大きな組み合わせでも安全に扱えます。パラメータ探索、ファイル名の展開、座標生成、テストケース列挙など、現場で出番が多い基本ツールです。

from itertools import product

colors = ["red", "blue"]
sizes  = ["S", "M", "L"]

for c, s in product(colors, sizes):
    print(c, s)
# red S, red M, red L, blue S, blue M, blue L
Python

基本の使い方(ここが重要)

イテラブルを渡すだけで「多重ループ」を代替できる

product(a, b, c) は「for x in a: for y in b: for z in c: …」と同じ順序で組み合わせを返します。各要素はタプルで得られ、アンパックして使うのが自然です。

from itertools import product

for x, y in product([1, 2], ["A", "B"]):
    print(x, y)  # (1, 'A'), (1, 'B'), (2, 'A'), (2, 'B')
Python

repeat で「同じ集合を n 回使う」直積を作る

product(iterable, repeat=n) は、同じイテラブルを n 回並べた直積を生成します。n 桁のパターンを作るときに便利です。

from itertools import product

# 3桁の2進数(0/1 の全組み合わせ)
for bits in product([0, 1], repeat=3):
    print(bits)  # (0,0,0) から (1,1,1) まで
Python

イテレータなので「必要な分だけ」取り出せる

list(product(…)) で全展開すると巨大になり得ます。基本は for で流し、必要なら islice(部分取り出し)や break で制御します。

from itertools import product, islice

pairs = product(range(1000), range(1000))
for x, y in islice(pairs, 10):  # 先頭10件だけ
    print(x, y)
Python

重要ポイントの深掘り(順序・サイズ・省メモリ・展開)

生成順序(左から右へ、内側が最後)

product(a, b, c) は「a の各要素について、b の各要素について、c を回す」という順序です。多重ループの展開順と一致します。出力の再現性が必要なときに重要です。

組み合わせ数は「要素数の積」になる

総数は len(a) × len(b) × …。サイズが爆発しやすいので、上限の見積もりとフィルタ条件(if で弾く、途中で打ち切る)を意識しましょう。

from itertools import product

# 3×4×5 = 60通り
count = sum(1 for _ in product(range(3), range(4), range(5)))
print(count)
Python

直積は「遅延生成」される(省メモリ)

product は1組ずつ作るため、巨大な検索空間でも扱えます。必要な条件を早めに評価して、無駄な分岐を避けるのがコツです。

from itertools import product

for a, b, c in product(range(1000), repeat=3):
    if a + b + c == 10:    # 条件成立時だけ使う
        print(a, b, c)
        break
Python

辞書や構成を「*展開」して柔らかく書く

可変長の集合群を持っているなら、で展開して product(iterables) とすれば柔軟に扱えます。

from itertools import product

spec = {
    "color": ["red", "blue"],
    "size":  ["S", "M"],
    "fit":   ["slim", "regular"],
}
keys = list(spec.keys())
for combo in product(*spec.values()):
    print(dict(zip(keys, combo)))
Python

実務での使いどころ(パラメータ探索・座標生成・ファイル展開)

パラメータグリッドの探索(小規模グリッドサーチ)

機械学習のハイパーパラメータやツールの設定の当たりを取るとき、全通りを product で回せば簡潔です。

from itertools import product

for lr, wd, bs in product([0.01, 0.001], [0.0, 1e-4], [32, 64]):
    print(f"lr={lr} wd={wd} bs={bs}")
Python

2次元・3次元の座標格子生成(画像・数値計算)

range と組み合わせて座標の全通りを作れます。numpy なしでもシンプルに書けます。

from itertools import product

W, H = 3, 2
coords = list(product(range(W), range(H)))  # (x, y)
print(coords)  # [(0,0),(0,1),(1,0),(1,1),(2,0),(2,1)]
Python

ファイル名やパスの展開(接頭辞・接尾辞・拡張子)

定型的な組み合わせで大量のファイル名を作るケースに向きます。生成しながら処理へ流すと効率的です。

from itertools import product

prefixes = ["report", "summary"]
dates    = ["2025-12-15", "2025-12-16"]
exts     = [".csv", ".json"]

for p, d, e in product(prefixes, dates, exts):
    name = f"{p}_{d}{e}"
    print(name)
Python

例題で身につける(定番から一歩先まで)

例題1:3桁の PIN 候補を列挙し、条件で絞る

from itertools import product

def valid_pins():
    for a, b, c in product(range(10), repeat=3):
        # 連続した重複を禁止
        if a == b == c: 
            continue
        yield f"{a}{b}{c}"

for pin in list(valid_pins())[:10]:
    print(pin)
Python

例題2:英字+数字の組み合わせ(テスト ID 生成)

from itertools import product
import string

letters = string.ascii_uppercase[:3]  # 'A','B','C'
digits  = "0123456789"

for L, D in product(letters, digits):
    print(f"{L}{D}")  # A0, A1, ..., C9
Python

例題3:座標の近傍(8近傍)の相対位置を生成

from itertools import product

neighbors = [(dx, dy) for dx, dy in product([-1, 0, 1], repeat=2) if not (dx == 0 and dy == 0)]
print(neighbors)  # 8方向
Python

例題4:仕様テーブルから全通りのテストケースを展開

from itertools import product

spec = {
    "role": ["admin", "user"],
    "lang": ["ja", "en"],
    "theme": ["light", "dark"],
}

keys = list(spec.keys())
cases = [dict(zip(keys, combo)) for combo in product(*spec.values())]
for case in cases:
    print(case)
Python

まとめ

itertools.product は「すべての組み合わせ(直積)」を遅延生成で安全に列挙するための基本ツールです。多重 for を1行にまとめ、repeat で同一集合の n 桁展開、*展開で柔軟な構成を扱えます。生成順は多重ループと同じ、総数は要素数の積で増えるため上限見積もりと途中打ち切りが実務の勘所。パラメータグリッド、座標格子、ファイル展開、テストケース列挙まで、まずは product を「組み合わせの標準手段」にすると、コードが短く、読みやすく、堅牢になります。

タイトルとURLをコピーしました