Skip to main content

Nested Loops: Patterns, Performance, and When to Avoid Them

Intermediate25 min6 exercises80 XP
0/6 exercises

Think about a spreadsheet. It has rows and columns. To read every cell, you go through each row, and for each row, you go through each column. That's two loops — one inside the other. That's a nested loop.

Nested loops show up everywhere in programming: printing grid patterns, searching through tables, generating combinations, and processing images pixel by pixel. They're powerful, but they can also be surprisingly slow if you're not careful.

In this tutorial, you'll learn how nested loops work, see practical examples with grids and combinations, understand why they can be slow, and discover when to use alternatives instead.

How Do Nested Loops Work in Python?

A nested loop is simply a loop inside another loop. The outer loop runs first. For each iteration of the outer loop, the inner loop runs completely from start to finish.

A basic nested loop
Loading editor...

Here's the key insight: if the outer loop runs n times and the inner loop runs m times, the code inside the inner loop executes n x m times total. Three rows and three columns means 9 total prints.

Counting nested loop iterations
Loading editor...

Working with 2D Data (Grids and Tables)

The most practical use of nested loops is working with two-dimensional data. A list of lists in Python represents a grid, table, or matrix. The outer loop goes through the rows, and the inner loop goes through the columns in each row.

Iterating through a 2D grid
Loading editor...

Sometimes you need the row and column index, not just the values. Use enumerate() for that.

Using enumerate with nested loops
Loading editor...

Here's a practical example: building a multiplication table.

Multiplication table with nested loops
Loading editor...

Generating Combinations with Nested Loops

Nested loops are perfect for generating every combination of items from two (or more) groups. The outer loop picks from the first group, and the inner loop picks from the second.

All combinations of colors and sizes
Loading editor...

With 2 colors and 3 sizes, you get 6 combinations. Every color is paired with every size. This is called the Cartesian product of the two lists.

Finding pairs with a target sum
Loading editor...

Building Patterns with Nested Loops

Pattern printing is a classic exercise for understanding nested loops. Each row is controlled by the outer loop, and the number of characters per row is controlled by the inner loop.

Right triangle with stars
Loading editor...

The trick is that the inner loop's range depends on the outer loop's variable. In row 1, the inner loop runs once. In row 2, twice. In row 5, five times. That creates the staircase shape.

Inverted triangle (simpler approach)
Loading editor...

Performance: Why Nested Loops Can Be Slow

A single loop over 1,000 items runs 1,000 times. A nested loop over 1,000 items runs 1,000 x 1,000 = 1,000,000 times. That's a million operations. Add a third level of nesting and you hit a billion. Nested loops multiply, and the numbers grow fast.

Computer scientists describe this with Big O notation. A single loop is O(n) — the time grows linearly with the data size. A nested loop is O(n²) — the time grows with the square of the data size. Double the input and the work quadruples.

Comparing single vs nested loop speed
Loading editor...

When to Avoid Nested Loops

Not every problem that looks like it needs nested loops actually does. Often there's a faster approach using sets, dictionaries, or built-in functions.

O(n²) — nested loop to check for duplicates
nums = [3, 1, 4, 1, 5, 9]
has_dup = False
for i in range(len(nums)):
    for j in range(i+1, len(nums)):
        if nums[i] == nums[j]:
            has_dup = True
print(has_dup)  # True
O(n) — use a set instead
nums = [3, 1, 4, 1, 5, 9]
has_dup = len(nums) != len(set(nums))
print(has_dup)  # True

The set version is not just shorter — it's dramatically faster. For 10,000 items, the nested loop version does 50 million comparisons. The set version does about 10,000 operations. That's 5,000 times faster.

O(n²) — nested loop to find a value
students = [
    {'name': 'Alice', 'id': 101},
    {'name': 'Bob', 'id': 102},
    {'name': 'Charlie', 'id': 103}
]
ids_to_find = [103, 101]

for target_id in ids_to_find:
    for s in students:
        if s['id'] == target_id:
            print(s['name'])
O(n) — build a dictionary first
students = [
    {'name': 'Alice', 'id': 101},
    {'name': 'Bob', 'id': 102},
    {'name': 'Charlie', 'id': 103}
]
ids_to_find = [103, 101]

lookup = {s['id']: s['name'] for s in students}
for target_id in ids_to_find:
    print(lookup[target_id])

Practice Exercises

These exercises will strengthen your understanding of nested loops. They start with basic patterns and move toward real-world problems.

Exercise 1: Print a Rectangle
Write Code

Print a rectangle of stars with 3 rows and 5 columns. Each row should have 5 stars with no spaces between them.

Expected output:

*****
*****
*****
Loading editor...
Exercise 2: Predict the Output
Predict Output

Without running the code, predict what it will print. Count the total number of lines in the output. Then run it to check.

Loading editor...
Exercise 3: Number Triangle
Write Code

Print a number triangle where each row contains the row number repeated. The triangle has 4 rows.

Expected output:

1
22
333
4444
Loading editor...
Exercise 4: Sum All Grid Values
Write Code

A grid of numbers is given. Use nested loops to calculate and print the sum of all values in the grid.

Expected output:

45
Loading editor...
Exercise 5: All Outfit Combinations
Write Code

Given a list of tops and bottoms, print every possible outfit combination followed by the total count.

Expected output:

shirt + jeans
shirt + shorts
sweater + jeans
sweater + shorts
hoodie + jeans
hoodie + shorts
Total outfits: 6
Loading editor...
Exercise 6: Fix the Coordinate Grid
Fix the Bug

This code is supposed to print a 3x3 coordinate grid, but it has a bug. The output should show each coordinate on its own line, with x going from 0 to 2 and y going from 0 to 2.

Expected output:

(0,0) (0,1) (0,2)
(1,0) (1,1) (1,2)
(2,0) (2,1) (2,2)

Find and fix the bug.

Loading editor...

Summary: Python Nested Loops

Here's what you learned about nested loops:
------
Nested loopA loop inside another loop
Total iterationsOuter count x Inner count
2D dataOuter loop = rows, inner loop = columns
CombinationsPair every item from group A with every item from group B
PerformanceO(n²) — doubles the input, quadruples the work
AlternativesSets and dictionaries often replace nested loops

Rules of thumb:

  • Think about data size before nesting loops
  • Use meaningful variable names (row/col, not i/j)
  • String multiplication ('*' * n) often replaces inner loops for patterns
  • When searching for items, a dictionary or set is almost always faster than a nested loop
  • What's Next?

    In the next tutorial — [How to Read Python Error Messages](/python/python-error-messages) — you'll learn to decode Python's error messages, fix the most common bugs, and stop fearing tracebacks. Debugging is a skill that makes everything else easier.