list comprehension
double iteration
Python
programming
duplicate question

Double Iteration in List Comprehension

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Double iteration in Python list comprehensions is a concise way to generate combinations, flattened results, or transformed pairs from multiple iterables. It is powerful, but readability can suffer when the logic becomes complex. Understanding execution order and alternatives helps you write clean and correct comprehension code.

Execution Order In Double Iteration

In a comprehension with two for clauses, the rightmost loop changes fastest, similar to nested loops.

python
pairs = [(x, y) for x in [1, 2] for y in [10, 20, 30]]
print(pairs)

Equivalent nested loop:

python
1pairs = []
2for x in [1, 2]:
3    for y in [10, 20, 30]:
4        pairs.append((x, y))

Both produce the same order. This mental model prevents mistakes when adding conditions.

Common Use Cases

Cartesian Product Style Pairs

Generate every combination from two iterables:

python
1letters = ["a", "b"]
2numbers = [1, 2, 3]
3result = [f"{l}{n}" for l in letters for n in numbers]
4print(result)

Flatten Nested Lists

Flatten one level of nesting:

python
matrix = [[1, 2], [3, 4], [5, 6]]
flat = [item for row in matrix for item in row]
print(flat)

Filtered Pair Generation

Add conditions at the end:

python
pairs = [(x, y) for x in range(5) for y in range(5) if x < y and (x + y) % 2 == 0]
print(pairs)

Conditions can reference variables from all previous loops in the comprehension.

Multiple Conditions And Readability

Complex comprehensions can become difficult to maintain. A practical rule:

  • If comprehension is one transformation and one filter, keep it inline.
  • If it has multiple branches or business rules, use explicit loops.

Readable code is usually better than shortest code.

python
1# Hard to read in one expression for many developers
2result = [
3    (a, b, a * b)
4    for a in values_a
5    for b in values_b
6    if a > 0 and b > 0 and (a + b) in allowed_sums
7]

When logic grows, switch to helper functions or loops.

Nested Comprehension Versus itertools.product

itertools.product is often clearer for cartesian products.

python
1from itertools import product
2
3pairs = [(x, y) for x, y in product([1, 2], [10, 20, 30])]
4print(pairs)

Performance is typically good and intent is explicit.

Generator Expressions For Large Data

List comprehensions materialize full output. For large combinations, use generator expressions to avoid high memory usage.

python
gen = ((x, y) for x in range(1_000_000) for y in range(2))
print(next(gen))
print(next(gen))

Use list conversion only at the boundary where full materialization is truly required.

Debugging Incorrect Results

If output order or values are wrong:

  1. Expand to explicit nested loops.
  2. Print intermediate variables.
  3. Rebuild comprehension after confirming correct loop order.

This approach catches most comprehension bugs quickly.

Performance Considerations

List comprehensions are usually fast in CPython for simple transformations. However, performance depends on algorithmic complexity. Double iteration can become O(n*m) rapidly, so optimize input size and filtering strategy first.

If heavy numeric operations are involved, NumPy vectorization may outperform Python loops significantly.

Refactoring Guidance

When converting nested loops to comprehensions, keep unit tests in place and verify result ordering explicitly. Small ordering differences can break downstream logic such as deterministic report generation or expected tuple indexing in machine learning feature preparation.

A useful approach is writing the loop version first, asserting behavior, then replacing with comprehension only if readability remains strong. This keeps expressiveness without sacrificing maintainability.

Common Pitfalls

  • Misunderstanding loop order in nested comprehensions.
  • Packing too much business logic into one unreadable expression.
  • Materializing huge outputs unintentionally.
  • Forgetting that conditions apply after earlier loops are bound.
  • Using double iteration when a direct data structure lookup would be cheaper.

Summary

  • Double iteration comprehensions mirror nested loops with concise syntax.
  • The rightmost loop changes fastest.
  • They are ideal for combinations, flattening, and filtered pair generation.
  • Prefer readability over clever one-liners for complex logic.
  • Use generators or alternative APIs for large-scale iteration workloads.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.