Python Programming from First Principles: Learn to Code, Think Computationally, and Solve Real-World Problems
PDFEPUB
BOOK 000 · CHAPTER 8 · Iteration Tools with`itertools`

Iteration Tools with itertools

On this pageCombinationsPermutationsCartesian ProductsChaining Iterables

Some problems require exploring structured combinations: forming pairs, generating permutations, Cartesian products of parameter sets, or merging sequences. Doing this manually is error-prone and memory-intensive.itertools supplies a suite of combinatorial and iterative generators—functions that produce values lazily, one at a time, without materializing all output at once. Combinatorial tools may still store their finite input pools; lazy output does not make an enormous search space small.

Combinations

A combination selects items without regard to order.

Signature:

combinations(iterable, r)

Generates r-length subsets where order does not matter.

For example, forming project pairs in a group of students:

from itertools import combinations

students = ["Ada", "Grace", "Alan"]

for pair in combinations(students, 2):
    print(pair)
Listing 358 — Combinations

Output

('Ada', 'Grace')
('Ada', 'Alan')
('Grace', 'Alan')

This produces all unique 2-person groups—valuable in co-occurrence analysis or team formation algorithms.

Permutations

In other scenarios, the order does matter—for example, generating possible task sequences, testing input arrangements, or exploring order-sensitive models.

Permutations help enumerate every possible ordered arrangement of a collection, making them essential in optimization, simulation, and combinatorial search problems.

Signature:

permutations(iterable, r)

For instance, if we want to generate all ordered pairs from a list of letters, permutations produces each possible arrangement:

from itertools import permutations

letters = ["A", "B", "C"]

for p in permutations(letters, 2):
    print(p)
Listing 359 — Permutations

Output

('A', 'B')
('A', 'C')
('B', 'A')
('B', 'C')
('C', 'A')
('C', 'B')

Here each pair appears in every possible order, giving a complete view of all ordered arrangements.

Cartesian Products

Some tasks require exploring every possible combination across two or more sets. This appears frequently in machine learning (hyperparameter grids), simulation studies, scheduling problems, or combining dimensions like color × size × shape.

The product function from itertools generates these combinations efficiently and lazily—no nested loops or temporary lists needed.

Signature:

product(iter1, iter2, ...)

It returns an iterator producing tuples that contain one element from each iterable.

Example:

The code below generates every combination of learning rate and batch size:

from itertools import product

learning_rates = [0.01, 0.1]
batch_sizes = [16, 32]

for combo in product(learning_rates, batch_sizes):
    print(combo)
Listing 360 — Cartesian Products

Output

(0.01, 16)
(0.01, 32)
(0.1, 16)
(0.1, 32)

product systematically pairs each learning rate with each batch size, giving all four combinations. This pattern is widely used in machine learning for hyperparameter tuning, where you try all combinations of parameter values to see which combination yields the best model performance. Using product makes such systematic exploration much easier and more scalable.

Chaining Iterables

Sometimes datasets come from different sources—multiple files, pages, or batches—but you want to iterate over all items as if they were one continuous sequence. The chain function from itertools provides exactly this: a lazy iterator that streams several iterables back-to-back without copying them.

Signature:

chain(iter1, iter2, ...)

The following code merges three lists of names into a single stream:

from itertools import chain

group1 = ["Ada", "Grace"]
group2 = ["Alan"]
group3 = ["Linus", "Margaret"]

for name in chain(group1, group2, group3):
    print(name)
Listing 361 — Chaining Iterables

Output

Ada
Grace
Alan
Linus
Margaret

chain yields items from each iterable in order, behaving like one long sequence. Because items are produced lazily, it scales efficiently to large datasets.