Floating Octothorpe

Python for else?

I've used Python for longer than I care to admit. It's a great language, and I would recommend getting started with it if you haven't already.

One of the nice things about programming is there is always something new to learn about or surprise you. Recently I stumbled across a feature of Python's loop statements that I have never seen before.

for and if statements

If you've done any programming before the concept of for and if statements shouldn't surprise you. for statements are used to iterate over a sequence (normally a list). For example:

>>> for name in ['Alice', 'Bob', 'Eve', 'Mallory']:
...     print('Hello', name)
...
Hello Alice
Hello Bob
Hello Eve
Hello Mallory

And if statements can be used conditionally to run code. For example:

>>> if x > 0:
...     print('x is positive')
... elif x < 0:
...     print('x is negative')
... else:
...     print('x is zero')
...
x is positive

But what happens if you add an else clause to a for statement?

Loop statements with an else clause

The code below is perfectly valid, all be it slightly pointless Python code:

for x in range(5):
    print(x)
else:
    print('Running else clause..')

Running this will produce the following output:

0
1
2
3
4
Running else clause...

So what's going on? When does the else clause not get executed? Well perhaps a better keyword for else, in this context, would have been nobreak. The else clause is only executed if the for statement iterates over everything without hitting a break statement. Adding a break statement to the example will prevent the else clause being executed:

>>> for x in range(5):
...     print(x)
...     break
... else:
...     print('Running else clause..')
...
0

Practical uses

One of the most common ways to use a for else loop is when searching through a sequence. The Python docs give the following example, which determines if n is prime:

for x in range(2, n):
    if n % x == 0:
        print(n, 'equals', x, '*', n//x)
        break
else:
    # loop fell through without finding a factor
    print(n, 'is a prime number')

This removes the need for having a flag variable; with a flag variable the code would look something like this:

is_prime = True
for x in range(2, n):
    if n % x == 0:
        print(n, 'equals', x, '*', n//x)
        is_prime = False
        break
if is_prime:
    # loop fell through without finding a factor
    print(n, 'is a prime number')

Other uses of else

There are actually a few other places you can use an else clause. While loops work in much the same way for loops do:

>>> i = 1
>>> while i < 5:
...     print('i: ', i)
...     if i % 3 == 0:
...         break
...     else:
...         i += 1
... else:
...     print('"i" was never divisible by 3')
...
i:  1
i:  2
i:  3

You can also have an else clause following a try statement:

>>> try:
...     x = 5/1
... except ZeroDivisionError:
...     print('Dividing by zero...')
... else:
...     print("We didn't divide by zero")
...
We didn't divide by zero

In the example above the else clause is executed if the try clause is completed without raising an error. However unlike code in the try clause, exceptions raised in the else clause are not handled by any preceeding except clauses.

Further reading

If you're still curious I would recommend reading the Python documentation on control flow and compound statements.

If after that you're still curious, Structured Programming with go to Statements by Donald Knuth is worth a read. It gives an interesting historical perspective on structured programming, before it was as ubiquitous as it is today.