livepython.net
CHAPTER 10For Loops
10.4  NESTED LOOPS

Nested Loops, break and continue in Python

Nested Loops: A Loop Inside a Loop

A loop's block can contain another loop. This is called a nested loop. For every single iteration of the outer loop, the inner loop runs all the way through.

PYTHONedit me
for shirt in ["red", "blue"]:
    for size in ["S", "M", "L"]:
        print(shirt, size)
OUTPUT
red S
red M
red L
blue S
blue M
blue L

Think of it like a clock: for every one step of the hour hand, the minute hand goes all the way round.

How it runs

  1. The outer loop takes "red".
  2. The inner loop runs completely: S, M, L.
  3. The outer loop takes "blue", and the inner loop starts again from S.

So the inner block runs 2 x 3 = 6 times: outer count times inner count.

Read the indentation

  • The outer for sits at the left edge.
  • The inner for is indented 4 spaces: it's inside the outer loop.
  • The inner block is indented 8 spaces: it's inside both loops.

It's the same idea as the nested if from chapter 8: each level adds 4 spaces.

With range()

Nested range() loops make every pair of numbers. Here is a small times table:

PYTHONedit me
for a in range(1, 3):
    for b in range(1, 4):
        print(a, "x", b, "=", a * b)
    print("---")
OUTPUT
1 x 1 = 1
1 x 2 = 2
1 x 3 = 3
---
2 x 1 = 2
2 x 2 = 4
2 x 3 = 6
---

The print("---") is indented 4 spaces, so it's inside the outer loop but after the inner one. It runs once per row, when the inner loop has finished.

Common beginner doubt: "Can I use the same variable name for both loops?" Don't. The inner loop would overwrite the outer one's value. Give each loop its own name, like a and b, or row and col.

For each outer item, the inner loop runs all the way through.

your turnPredict the output

What will this print?

for x in ["A", "B"]: for n in [1, 2]: print(x, n)
Your turn! What will this code show on the screen?
your turnType the output

Type what this prints

count = 0 for i in range(3): for j in range(4): count += 1 print(count)
Read the code line by line, then type the output exactly.

Print Patterns with Nested Loops

Nested loops are perfect for patterns: the outer loop makes the rows, the inner loop makes the characters in each row.

PYTHONedit me
for row in range(3):
    for col in range(5):
        print("*", end="")
    print()
OUTPUT
*****
*****
*****

Think of it like knitting a scarf: you knit a row stitch by stitch, then turn and start the next row.

Two print tricks from chapter 2

  • print("*", end="") prints a star and stays on the same line.
  • An empty print() prints nothing but a line break. It ends the row.

The empty print() is indented 4 spaces: it runs once per row, after the inner loop.

A triangle

Let the inner loop depend on the row number, and each row gets longer:

PYTHONedit me
for row in range(1, 5):
    for col in range(row):
        print("*", end="")
    print()
OUTPUT
*
**
***
****

Row 1 has 1 star, row 2 has 2 stars, and so on, because the inner loop runs range(row).

A shortcut for one character

For a row made of one repeated character, * from chapter 5 can replace the inner loop:

PYTHONedit me
for row in range(1, 5):
    print("*" * row)
OUTPUT
*
**
***
****

Both ways are right. The nested loop is worth knowing, because it also works when each position needs its own work, like printing numbers:

PYTHONedit me
for row in range(1, 4):
    for n in range(1, row + 1):
        print(n, end=" ")
    print()
OUTPUT
1
1 2
1 2 3

Common beginner doubt: "Why do I get all the stars on one long line?" You forgot the empty print() after the inner loop, or it isn't indented under the outer loop.

The outer loop makes the rows; the inner loop fills each row.

your turnFill the gap

Print a triangle that grows by one star per row

for row in range(1, 4): for col in range(?): print("*", end="") print()

It should print: * ** ***

Which piece makes this code work?
your turnPredict the output

What will this print?

for row in range(2): for col in range(3): print("#", end="") print()
Your turn! What will this code show on the screen?

Stop a Loop Early with break

break stops a loop straight away, even if there are items left. Python jumps to the first line after the loop.

PYTHONedit me
names = ["Sunny", "Rocky", "Lucky"]
for name in names:
    print("Checking", name)
    if name == "Rocky":
        print("Found Rocky!")
        break
print("Search over")
OUTPUT
Checking Sunny
Checking Rocky
Found Rocky!
Search over

Lucky is never checked: once Rocky is found, there's no reason to keep looking.

Think of it like looking for your keys: you check one pocket after another, and you stop the moment you find them.

The rules

  • break almost always sits inside an if: "stop when this happens".
  • Lines after break in the same block don't run.
  • Inside a nested loop, break stops only the loop it's in: the inner one.

Found or not?

To know afterwards whether the loop found something, use a True/False variable, often called a flag:

PYTHONedit me
nums = [3, 8, 12, 5]
found = False
for n in nums:
    if n > 10:
        found = True
        print("First number over 10:", n)
        break
if not found:
    print("No number over 10")
OUTPUT
First number over 10: 12

Change 12 to 2 and run it again: the flag stays False, so the last if reports it.

For a plain "is it in the list?" question, in from chapter 9 is shorter. break is for when you need the item itself, or want to do something the moment you find it.

Common mistake: break outside a loop. Python stops with SyntaxError: 'break' outside loop, because there's no loop to stop.

break stops the loop at once and jumps to the line after it.

your turnPredict the output

What will this print?

for n in [1, 2, 3, 4]: if n == 3: break print(n)
Your turn! What will this code show on the screen?
your turnFix the code

Make it print only the first price over 100

It should print: 150

for price in [40, 150, 90, 300]:
    if price > 100:
        print(price)
This code does not work yet. Fix it, then press Run.

Skip an Item with continue

continue skips the rest of the block for the current item and jumps straight to the next item. The loop itself keeps going.

PYTHONedit me
for n in [5, -3, 8, -1, 2]:
    if n < 0:
        continue
    print(n)
OUTPUT
5
8
2

The negative numbers reach continue, so their print() is skipped. Everything else is printed.

Think of it like sorting post: when a letter isn't for you, you put it aside and pick up the next one. You don't stop sorting.

break or continue?

KeywordWhat happensLike…
breakthe whole loop stopsleaving the queue
continueonly this item is skippedletting one person go ahead

Skip the bad, handle the good

continue keeps the main code at one level of indentation. Here it skips the spaces and counts the rest:

PYTHONedit me
text = "hi there sunny"
letters = 0
for ch in text:
    if ch == " ":
        continue
    letters += 1
print("Letters:", letters)
OUTPUT
Letters: 12

The same program without continue would put letters += 1 inside if ch != " ":. Both are right. With continue, the "skip" rule sits at the top, and the main work stays easy to read, which helps when there are several lines of it.

Common beginner doubt: "Do I always need break or continue?" No. Most loops don't use either. Reach for them when the loop has an exception to its normal work: stop when found, or skip what doesn't belong.

continue skips to the next item; the loop carries on.

your turnPick the right idea

You loop over a list of marks and want to ignore the zeros but still look at every other mark. Which keyword fits?

Think about it, then pick one.
your turnPredict the output

What will this print?

for ch in "a-b-c": if ch == "-": continue print(ch, end="")
Your turn! What will this code show on the screen?

Common for Loop Mistakes

These are the for loop mistakes every beginner makes. Most of them give no error at all, so it pays to know them by sight.

Think of this list as a mechanic's checklist: when a loop misbehaves, go through it from the top.

1. print() inside instead of after

PYTHONedit me
total = 0
for n in [10, 20, 30]:
    total += n
    print("Total:", total)
OUTPUT
Total: 10
Total: 30
Total: 60

You wanted one line. The print() is indented, so it runs every time. Move it to the left edge, and it runs once, after the loop.

2. Resetting inside the loop

total = 0 inside the loop starts the total again on every item (topic 3). Set it up before the loop.

3. Off by one with range()

range(1, 10) stops at 9. To include 10, write range(1, 11) (topic 2).

4. Looping over a number

PYTHONedit me
count = 3
for i in count:
    print("Hi")
OUTPUT
TypeError: 'int' object is not iterable

A number isn't a list of items. Don't worry: the fix is range(count).

5. Changing the list you're looping over

Removing or adding items to the list while a for loop goes through it makes the loop skip items or never end:

nums = [1, 2, 3]
for n in nums:
    nums.append(n)   # never do this: the list keeps growing, so the loop never ends

Build a new list instead, with append() (topic 3).

6. The colon and the indentation

for x in items without : is a SyntaxError, and a block that isn't indented is an IndentationError (topic 1).

Check where the print is, where the start value is, the range, the colon and the indentation.

your turnSpot the bug

Which line breaks?

One line stops this program. Tap it.
your turnPredict the output

What will this print?

a = int(input()) b = int(input()) print(a + b)

The user types: 45

Your turn! What will this code show on the screen?

Practice: Nested loops

Solve these to lock in what you learned in this topic. Each one runs in your browser.

  1. 88.Python Program to Print a Star TriangleMediumSolve
  2. 89.Python Program to Print Prime Numbers up to NHardSolve