Nested Loops
A nested loop is a loop inside another loop. The inner loop completes all its iterations for each single iteration of the outer loop. Nested loops are useful for rows and columns, coordinate grids, tables, 2D structures and pattern generation.
Learning Objective
- 11.1.2.7 Use nested loops when solving problems
Nested Statements
Craig'n'Dave — nested structures and nested statement examples.
Conceptual Anchor
The Clock Analogy
Think of a clock. The minute hand behaves like the inner loop: it completes many values before the hour hand, the outer loop, moves to its next value. Then the minute hand starts its cycle again.
hour = 1 → minute: 0, 1, 2, 3, ...
hour = 2 → minute starts again from 0
Rows, Columns & Nested-Loop Mechanics
for i in range(3)
i changes only after the whole inner loop finishes.
for j in range(4)
j moves through all four values for every value of i.
Anatomy of Nested Loops
for i in range(3): # outer loop
for j in range(4): # inner loop
print(i, j) # bodyfor i in range(3)Outer loop
Controls the slower-changing dimension: usually rows, groups or larger cycles.
for j in range(4)Inner loop
Runs from start to finish for every single outer-loop value.
print(i, j)Body
Runs once for every valid pair of outer and inner values.
Key Rule
For every single value of i, the inner loop runs completely from
start to finish. Only after that does i move to its next
value.
i = 0
i = 1
i = 2
Nested Loop Tracer
Follow the exact order in which the nested loop visits each coordinate. Watch what happens when the inner range is exhausted.
for i in range(3):
for j in range(4):
print(i, j)
——0 / 12
Watch the reset
After j = 3, the inner range is exhausted. The outer loop advances to the
next i, and the inner loop starts again at j = 0.
Nested Loop Grid Explorer
Trace Tables for Nested Loops
Recommended tracing method
Use one row for every execution of the innermost body. Record every changing loop variable, any calculated value, and the output.
1. Worked Trace Table Example
for i in range(2):
for j in range(3):
x = i + j
print(x)| Step | i | j | x = i + j | Output |
|---|---|---|---|---|
| 1 | 0 | 0 | 0 | 0 |
| 2 | 0 | 1 | 1 | 1 |
| 3 | 0 | 2 | 2 | 2 |
| 4 | 1 | 0 | 1 | 1 |
| 5 | 1 | 1 | 2 | 2 |
| 6 | 1 | 2 | 3 | 3 |
What the table reveals
i changes 0 → 1, while j runs 0 → 1 →
2 for each value of i. When i becomes 1,
j resets to 0.
2. Guided Trace Practice
for row in range(1, 4):
for col in range(1, 3):
value = row * col
print(value, end=" ")| Step | row | col | value | Output |
|---|
3. Independent Trace Practice
for i in range(1, 4):
for j in range(i):
print(j, end="")
print()Before revealing the template, decide how many rows your trace table needs. Then trace every execution of the inner body.
Fixed vs Dependent Inner Ranges
Fixed inner range
for i in range(3):
for j in range(4):
...
Dependent inner range
for i in range(1, 6):
for j in range(i):
...
Important rule
Multiplying outer_count × inner_count works when the inner loop has the same
number of iterations every time. With a dependent range, add the inner-loop counts for
each outer value.
Pattern Growth Visualizer
Predict the Output
Where Should print() Go?
Coordinate Grid Explorer
Nested loops often model a 2D position. The outer variable can represent a row, while the inner variable represents a column.
Click a cell. row = i = ? column = j = ?
Worked Examples
More Nested-Loop Structures
for outside, while inside
for i in range(3):
j = 0
while j < 2:
print(i, j)
j += 1
Nested loops do not have to be two for loops. The same outer/inner rule
still applies.
One outer loop, multiple inner loops
for i in range(1, n + 1):
for s in range(n - i):
print(" ", end="")
for j in range(1, i + 1):
print(j, end="")
print()
Both inner loops execute in sequence for every value of the outer variable.
Same Variable Experiment
for i in range(3):
print("outer before:", i)
for i in range(2):
print("inner:", i)
print("outer after:", i)
Predict the value shown by outer after before reading the explanation.
Key idea: the inner loop assigns values to the same name
i. The current outer value is no longer available after the inner loop
finishes. On the next outer iteration, Python assigns the next outer value again.
Performance & Debugging
Execution Count Calculator
Nested Loop Error Lab
Pitfalls & Common Errors
Reusing the same loop variable
The inner loop reassigns the same variable name during its execution. This makes the
current outer value unavailable inside/after the inner loop body. Prefer distinct names
such as i/j or row/col.
Misplaced print()
For row-based patterns, the blank print() used for a new line normally
belongs inside the outer loop but after the inner loop.
Multiplying counts when the range is dependent
outer × inner only works for a fixed inner count. If the inner range depends
on the outer variable, add each inner count.
Performance grows quickly
1000 outer iterations × 1000 inner iterations = 1,000,000 body executions. Three nested loops of 100 each also produce 1,000,000 executions.
Pro-Tips for Exams
Nested-Loop Strategy
- Identify the outer variable and inner variable first.
- Trace the full inner loop for the first outer value.
- When the inner loop is exhausted, reset it and move to the next outer value.
- For fixed inner ranges, total body executions can be found by multiplication.
- For dependent inner ranges, add the number of inner iterations for each outer value.
- For pattern questions, identify the number of rows and what changes on each row.
- Use a trace table when more than one variable changes.
Graded Tasks
How many times does the innermost body execute in
for i in range(5): for j in range(3): ...?
Explain the difference between the outer and inner loop and describe when the inner variable resets.
Explain why a blank print() is often placed after the inner loop but
still inside the outer loop.
Write nested loops that print a rectangle with 4 rows and 7 stars per row.
Write an inverted triangle with 5 stars on the first row down to 1 star on the last row.
Print all pairs (i, j) where i + j == 10 and both values
are between 1 and 9.
Complete a trace table for
for i in range(1,4): for j in range(i): x=i+j. Include Step, i, j and
x.
Create a number or star pattern whose number of inner-loop iterations changes on each row.
Challenge: Diamond pattern
Create a centered diamond of stars with height 7: three growing rows, one middle row, and three shrinking rows.
Exam Practice
Q1: Write the exact output. [3]
for i in range(2):
for j in range(3):
print(i + j, end=" ")
print()Reveal marking points
Q2: State how many times the body executes.
[1]for i in range(4): for j in range(5): print(i, j)
Reveal marking point
Q3: Calculate the total number of inner-loop executions. [2]
for i in range(1, 5):
for j in range(i):
print("*", end="")Reveal marking points
Q4: Complete the trace table for the program below. [4]
for i in range(2):
for j in range(2):
x = i * 10 + j
print(x)| Step | i | j | x | Output |
|---|---|---|---|---|
| 1 | ? | ? | ? | ? |
| 2 | ? | ? | ? | ? |
| 3 | ? | ? | ? | ? |
| 4 | ? | ? | ? | ? |
Reveal completed trace table
Self-Check Quiz
for i in range(1,4): for j in range(i), how
many inner executions occur?