python 32 lines · 7 steps

Generating product variants with itertools.product

Expand option groups into every combination, pricing each variant with per-option surcharges.

Explained by highlit
1from itertools import product
2from dataclasses import dataclass
3from decimal import Decimal
4 
5 
6@dataclass(frozen=True)
7class Variant:
8 sku: str
9 options: dict[str, str]
10 price: Decimal
11 
12 
13def build_variants(base_sku: str, base_price: Decimal, option_groups: dict[str, list[str]]) -> list[Variant]:
14 surcharges = {
15 ("size", "XL"): Decimal("3.00"),
16 ("size", "XXL"): Decimal("5.00"),
17 ("material", "organic"): Decimal("4.50"),
18 }
19 
20 names = list(option_groups)
21 variants: list[Variant] = []
22 
23 for combo in product(*option_groups.values()):
24 selection = dict(zip(names, combo))
25 price = base_price + sum(
26 (surcharges.get(pair, Decimal("0")) for pair in selection.items()),
27 Decimal("0"),
28 )
29 suffix = "-".join(value.upper()[:3] for value in combo)
30 variants.append(Variant(sku=f"{base_sku}-{suffix}", options=selection, price=price))
31 
32 return variants
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1itertools.product turns a mapping of option lists into every possible combination without nested loops.
  2. 2Zipping the original keys back onto each combo tuple restores which value belongs to which option.
  3. 3Using Decimal for money keeps surcharge arithmetic exact instead of drifting with float rounding.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Generating product variants with itertools.product — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code