A nested loop is a loop written inside another loop. The inner loop runs completely from start to finish every single time the outer loop goes round once. Nested loops are how programs handle grids, tables, patterns and any problem with two dimensions.

A first example

for row in range(3):
    for column in range(4):
        print(row, column)

The outer loop runs three times. Each of those times, the inner loop runs four times. So print is called 3 × 4 = 12 times, producing every combination of row and column:

0 0
0 1
0 2
0 3
1 0
1 1
...
2 3

Look at how the numbers change. The right-hand number cycles through 0–3 quickly; the left-hand one only advances after the right-hand one has finished a full cycle. That is exactly how a car odometer works, and it is the single most useful mental image for nested loops.

The counting rule

Total iterations of the inner block = outer repetitions × inner repetitions.

Outer loop Inner loop Inner block runs
3 times 4 times 12 times
5 times 5 times 25 times
10 times 10 times 100 times
100 times 100 times 10,000 times

That last row is worth pausing on. Nesting multiplies work, so a nested loop over a large list becomes slow very quickly. This is why the sorting algorithms that use nested loops are described as O(n²) — double the list length and the work quadruples.

Building a pattern

Nested loops are how you draw shapes made of characters.

A rectangle:

for row in range(4):
    for star in range(6):
        print("*", end="")
    print()

Output:

******
******
******
******

The end="" stops print from starting a new line after each star, so the inner loop builds one row across the screen. The bare print() after the inner loop — indented to the level of the outer loop — ends the row. Getting that indentation right is the whole trick.

A triangle, by making the inner loop's length depend on the outer variable:

for row in range(1, 6):
    for star in range(row):
        print("*", end="")
    print()

Output:

*
**
***
****
*****

On the first pass row is 1, so the inner loop runs once. On the fifth pass row is 5, so it runs five times. The inner loop does not have to be a fixed length.

Working through a grid

The commonest real use of nested loops is stepping through a two-dimensional list.

scores = [
    [7, 9, 4],
    [6, 8, 10],
    [5, 5, 9]
]

total = 0
for row in scores:
    for value in row:
        total = total + value

print("Total:", total)

The outer loop takes one row at a time; the inner loop takes each value within that row. The running total is declared outside both loops, because it must survive from one row to the next.

Printing the grid neatly uses the same shape:

for row in scores:
    for value in row:
        print(value, end=" ")
    print()

Tracing a nested loop by hand

The reliable way to check a nested loop is a trace table. For:

for i in range(2):
    for j in range(3):
        print(i * j)
Pass i j i * j
1 0 0 0
2 0 1 0
3 0 2 0
4 1 0 0
5 1 1 1
6 1 2 2

Six rows, because 2 × 3 = 6. Write out the table whenever a nested loop is not behaving as you expect — the pattern of which variable changes fastest usually reveals the bug immediately.

Common mistakes to avoid

  • Wrong indentation. In Python, indentation is the structure. A line indented one level too far ends up inside the inner loop and runs far more often than intended.
  • Reusing the same variable name for both loops. for i in range(3): for i in range(3): will confuse the interpreter and you. Use different names — row and column, or i and j.
  • Resetting a total inside the inner loop, so it never accumulates across rows.
  • Forgetting end="" when building a row of output, so every character lands on its own line.
  • Nesting a while loop whose condition is never updated, which produces an infinite loop that never returns control to the outer loop.

When not to nest

If you find yourself writing three or four levels of nesting, it is usually a sign the problem should be broken up. Moving the inner work into a function makes the code much easier to read:

def row_total(row):
    total = 0
    for value in row:
        total = total + value
    return total

grand_total = 0
for row in scores:
    grand_total = grand_total + row_total(row)

The nesting has not disappeared, but each piece is now short enough to understand on its own — which is a habit worth building long before it becomes essential.

Frequently asked questions

How many times does the inner loop actually run?

Multiply the two counts together. An outer loop running 5 times containing an inner loop running 3 times executes the inner block 15 times in total. The inner loop restarts from the beginning on every pass of the outer loop — it does not carry on from where it stopped. If the inner loop's length depends on the outer variable, as in the triangle example, add up the individual lengths instead: 1 + 2 + 3 + 4 + 5 = 15.

Can you nest a while loop inside a for loop?

Yes, and any other combination too — for inside while, while inside while, and so on. The rules are the same regardless of loop type. Be especially careful with a nested while: its condition variable must be updated inside the loop, and if it needs to start fresh on each outer pass, it must be reset at the top of the outer loop rather than before it.

Why does my nested loop print everything on separate lines?

Because print adds a newline by default. To build up a single row of output, use print(value, end=" ") inside the inner loop so nothing moves to a new line, then put a plain print() after the inner loop — indented to the outer loop's level — to finish the row. If that final print() is indented too far it will run after every character and the problem returns.

Are nested loops slow?

They can be, because the work multiplies rather than adds. Two nested loops over a list of 1,000 items perform a million operations. For small grids this is irrelevant; for large datasets it matters a great deal, and it is the reason simple sorting algorithms with nested loops are much slower than clever ones on big lists. If a nested loop feels slow, ask whether the same result could be reached in a single pass.


For Socratic KS3 computing tutoring — Python, loops and beyond — visit aitutors.me.