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
for value in values:
statement
else:
statement <- runs when the values ran out
skipped when a break was reachedThe 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
# 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')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.
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:
# 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')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.
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:
Search for a number that is on the list, then for one that is not.
It cannot be decided yet — it depends on whether a break is reached before the values run out.
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.
# 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')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:
# 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')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:
# 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')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:
# 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')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.
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:# 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')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
# 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')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.
9Recap
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.When does the else block of a for loop run?
A for loop has an else block and no break anywhere inside it. What can you say about the else?
What does the loop else save you writing?