LambdaLabTM
Computer Science · Class 11 · Jump Statements
Types of StatementsJump⏱️ 12 min read

else with a Loop

Python lets you attach an else to a for or a while, and it does not mean what you think. There is no condition for it to be the opposite of. It runs when the loop finished normally — which is to say, when no break was ever reached. That is why this lesson comes last: without break, a loop else has nothing to do.

1How it is written

shape.py
for value in values:
    statement
else:
    statement    <- runs when the values ran out
                    skipped when a break was reached

The else sits at the same indentation as the for — not indented inside it. It is part of the loop statement, the way else is part of an if.

2With no break anywhere, it always runs

else_plain.py
# use of else with a for loop
for i in range(1, 6):
    print(i)
else:
    print('You just printed all the numbers from 1 to 5')
Output
1
2
3
4
5
You just printed all the numbers from 1 to 5

The values ran out, the loop ended the ordinary way, and the else block ran. Which makes it, in this program, completely pointless — the same line printed after the loop with no else at all would do exactly the same thing.

Note
A loop else with no break in the loop is always pointless. It runs every time, so it might as well be an ordinary statement below the loop. The else only earns its place when there is a break that might skip it.

3Add a break, and it is skipped

Same loop, same else, with a break that fires on the third round:

else_break.py
# the same loop, with a break
for i in range(1, 6):
    if i == 3:
        break
    print(i)
else:
    print('You just printed all the numbers from 1 to 5')
Output
1
2

The else block did not run. The loop did not finish — it was broken out of — and that is the one thing that stops an else.

Key Takeaway
The else block of a loop runs only if the loop terminated normally, without hitting a break. Read the two words for … else as “did the loop get all the way through?”, not as “otherwise”.

4Watch it decide

A search over a small list. Pick a number that is on it and the break fires, so the else is skipped; pick one that is not and the values run out, so the else runs. The program is identical either way — only the value of wanted changes:

🏁 Did the loop finish, or was it broken?

Search for a number that is on the list, then for one that is not.

wanted =on the list
n = 4
search.py
loop headerif headerbody — the indented blockoutside
numbers = [4, 8, 15, 16]
wanted = 15
for n in numbers:
print('Looking at', n)
if n == wanted:
print('Found it')
break
else:
print('Not on the list')
the else block
waiting

It cannot be decided yet — it depends on whether a break is reached before the values run out.

output

The header hands out the next value: n is now 4.

5What it is really for: saying “not found”

Searching a list is easy. Reporting that the thing was not there is the awkward part, because you only know it once every value has been checked — and by then the loop is over.

The usual answer is a flag: a variable that remembers.

search_flag.py
# the flag way: a variable remembers whether we found it
names = ['Aarav', 'Diya', 'Kabir', 'Meera']
wanted = 'Sara'
found = 0

for name in names:
    if name == wanted:
        found = 1
        break

if found == 1:
    print('Found', wanted)
else:
    print(wanted, 'is not on the list')
Output
Sara is not on the list

It works, and it costs a variable, two extra lines and a second if that repeats the decision the loop already made. The loop else does the same job without any of that:

search_else.py
# the same search, using else on the loop
names = ['Aarav', 'Diya', 'Kabir', 'Meera']
wanted = 'Sara'

for name in names:
    if name == wanted:
        print('Found', wanted)
        break
else:
    print(wanted, 'is not on the list')
Output
Sara is not on the list

No flag, no second if. The break is the “found it” path and the else is the “got to the end without finding it” path.

6The classic: is it a prime number?

A prime number has no factor except 1 and itself. So: check every number from 2 up to n - 1, and if even one of them divides n exactly, n is not prime — and there is no point checking the rest.

That is a search, so it has the same two shapes. First with a flag:

prime_flag.py
# is n a prime number? (using a flag)
n = 15
flag = 0

for i in range(2, n):
    if n % i == 0:
        flag = 1
        break

if flag == 0:
    print(n, 'is a prime number')
else:
    print(n, 'is not a prime number')
Output
15 is not a prime number

With n as 15, the loop checks 2 (no), then 3 — and 15 % 3 is 0, so flag becomes 1 and the break stops the search. Numbers 4 to 14 are never tested, which is the whole point of the break.

Now the same program with else on the loop:

prime_else.py
# the same check, using else on the loop
n = 15

for i in range(2, n):
    if n % i == 0:
        print(n, 'is not a prime number')
        break
else:
    print(n, 'is a prime number')
Output
15 is not a prime number

Shorter, and it says what it means: if a factor was found, break out and report it; if the loop got all the way through without finding one, it is prime. Change n to 13 and the loop tests 2 up to 12, finds nothing, ends normally, and the else prints 13 is a prime number.

Watch Out
This program is wrong for 0, 1 and 2 — including the version in most textbooks. With n as 1, range(2, 1) is empty, so the loop body never runs at all; the loop ends normally, the else runs, and the program announces that 1 is a prime number. It is not — a prime must have exactly two factors, and 1 has one. We ran it to check. The repair is a guard before the loop:
prime_fixed.py
# the fix: rule out everything below 2 first
n = 1

if n < 2:
    print(n, 'is not a prime number')
else:
    for i in range(2, n):
        if n % i == 0:
            print(n, 'is not a prime number')
            break
    else:
        print(n, 'is a prime number')
Output
1 is not a prime number

Read the indentation carefully in that one. The second else lines up with the for, so it belongs to the loop; the first lines up with the if, so it belongs to the if. Same word, two different statements, and only the indentation says which is which.

7It works on while too

while_else.py
# else works the same way with while
i = 1

while i <= 5:
    print(i)
    i = i + 1
else:
    print('The while loop ended on its own')
Output
1
2
3
4
5
The while loop ended on its own

The rule is unchanged: the else runs because the condition finally became False and no break was reached. Put a break in the body and it would be skipped, exactly as with for.

8Try it

Change wanted to a name that is on the list, then to one that is not. Only one of the two messages ever prints — the break and the else cannot both happen.

attendance.py

9Recap

Key Takeaway
An else block attached to a for or while loop runs only if the loop ended normally — the values ran out, or the condition became False — and is skipped if a break was reached. It lines up with the loop header, not inside it. Its real use is the “not found” case of a search, where it replaces a flag variable and a second if.
Note
That is the last of the five kinds of statement — sequential, selection, iterative, empty and jump. The map you were shown at the start of the chapter should read as a summary now rather than a preview. Go back to Introduction to Statements and see.
Quick Check

When does the else block of a for loop run?

Quick Check

A for loop has an else block and no break anywhere inside it. What can you say about the else?

Quick Check

What does the loop else save you writing?