Nested loops are a fundamental technique in Python for handling multi-dimensional data or performing operations on every combination of items from two or more iterables — such as lists of lists, rows and columns in a matrix, keys and values in nested dictionaries, or products of multiple sequences. The outer loop runs once for each item in its iterable, and for every outer iteration, the inner loop runs completely over its own iterable. This creates all possible pairings (Cartesian product) and is essential for grid processing, matrix operations, grouping, filtering across categories, and building combinations.
In 2026, nested loops remain essential — especially for data transformation, cross-tabulation, coordinate generation, and when list comprehensions become too complex or unreadable. Here’s a complete, practical guide to nested loops: basic syntax, real-world patterns, performance considerations, and modern best practices with type hints, alternatives, and safety.
The classic form: outer loop over one sequence, inner loop over another — print or process every combination.
colors = ["red", "green", "blue"]
sizes = ["small", "medium", "large"]
for color in colors:
for size in sizes:
print(f"{color} {size}")
# Output:
# red small
# red medium
# red large
# green small
# green medium
# green large
# blue small
# blue medium
# blue large
Real-world pattern: generating all pairs or combinations — very common for product options, grid coordinates, cross-tabulation, or testing all possibilities.
# All possible (x, y) points in a 5x5 grid
points = []
for x in range(5):
for y in range(5):
points.append((x, y))
print(points[:5]) # [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4)]
print(len(points)) # 25
Another everyday use: nested loops with list comprehensions — compact and fast for generating combinations or flattening nested structures.
# All combinations of two numbers from 1 to 3 (list comprehension style)
combinations = [(i, j) for i in range(1, 4) for j in range(1, 4)]
print(combinations)
# [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)]
# Flatten a list of lists
matrix = [[1, 2], [3, 4], [5, 6]]
flat = [num for row in matrix for num in row]
print(flat) # [1, 2, 3, 4, 5, 6]
Best practices make nested loops safe, readable, and efficient. Keep nesting shallow — max 2–3 levels; deeper nesting hurts readability — flatten with comprehensions or itertools.product() instead. Use meaningful variable names — for row in matrix: for cell in row: — never for i in l: for j in m:. Prefer itertools.product() for Cartesian products — list(product(colors, sizes)) — it’s clearer, faster, and handles any number of iterables. Add type hints for clarity — list[tuple[str, str]] — improves readability and mypy checks. Avoid modifying outer iterable inside inner loop — it can cause skips or RuntimeError; collect changes in a new list. Modern tip: use enumerate() in outer loop when you need row/column indices — for row_idx, row in enumerate(matrix):. In production, wrap nested iteration over external data (files, APIs) in try/except — handle bad inner items gracefully without crashing the whole process. Combine with zip() for parallel nested iteration — for row, header in zip(data_rows, headers):.
Nested loops are how Python handles multi-dimensional or combinatorial data — powerful for grids, products, cross-references, and transformations. In 2026, use them with meaningful names, shallow depth, itertools.product() for clarity, and type hints for safety. Master nested loops (and their comprehension/itertools alternatives), and you’ll process complex data structures with confidence and elegance.
Next time you need every combination or nested traversal — reach for nested loops (or product()). It’s Python’s clean way to say: “Do this for every item in this, and every item in that.”