The controversial for...else statement in Python

[CG]Maxime
840 views

Open Source Your Knowledge, Become a Contributor

Technology knowledge has to be shared and made accessible for free. Join the movement.

Create Content

The controversial for...else statement in Python

Among all the great features Python has to offer, the for...else statement is one of my favorites. However, when I talk about it, it seems that people do not really see the point of it. I'll show you what it does, how to use it and, more importantly, how not to use it.

In a loop, the else clause is executed at the end of the loop if it hasn't been terminated by a break, a return or an exception. Note that it will also be executed even if the body of the loop was never entered (e.g. iteration over an empty list). Here's a simple example from the official documentation, feel free to play with the code.

For-Else Example
1
2
3
4
5
6
7
8
9
10
# Primality test all the numbers from 2 to 9.
for n in range(2, 10):
# Look for a divisor of n
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')
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Without using the else statement, the easy solution would be to use a variable and test the variable at the end of the loop:

For-Else Example
1
2
3
4
5
6
7
8
9
10
11
12
13
# Primality test all the numbers from 2 to 9.
for n in range(2, 10):
# Look for a divisor of n
d = None
for x in range(2, n):
if n % x == 0:
d = x
break
if d is None:
# loop fell through without finding a factor
print(n, 'is a prime number')
else:
print(n, 'equals', d, '*', n//d)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Actually, when I feel the need of a for-else, the pattern is always the same:

found = False
for x in l:
    if check_condition(x):
        do_something(x)
        found = True
        break
if not found:
    do_something_else()

...becomes:

for x in l:
    if check_condition(x):
        do_something(x)
        break
else:
    do_something_else()

The main argument against the use of the for-else structure is the possible lack of code readability. For instance, people may believe that the else belongs to the if instead of the for. As a consequence, I'd recommend to seek for an alternative solution when possible.

In the first example, you could use a generator:

For-Else Example
1
2
3
4
5
6
7
8
9
10
# Primality test all the numbers from 2 to 9.
for n in range(2, 10):
# Generator that gives all the divisors of n:
divisors = (x for x in range(2, n) if n % x == 0)
# Take first divisor
d = next(divisors, None)
if d is None:
print(n, 'is a prime number')
else:
print(n, 'equals', d, '*', n//d)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

And in a lot of cases, you can use any:

if any(check_condition(x) for x in l):
    do_something()
else:
    do_something_else()
Open Source Your Knowledge: become a Contributor and help others learn. Create New Content