Skip to content
Advertisement

Why does python use ‘else’ after for and while loops?

I understand how this construct works:

for i in range(10):
    print(i)

    if i == 9:
        print("Too big - I'm giving up!")
        break
else:
    print("Completed successfully")

But I don’t understand why else is used as the keyword here, since it suggests the code in question only runs if the for block does not complete, which is the opposite of what it does! No matter how I think about it, my brain can’t progress seamlessly from the for statement to the else block. To me, continue or continuewith would make more sense (and I’m trying to train myself to read it as such).

I’m wondering how Python coders read this construct in their head (or aloud, if you like). Perhaps I’m missing something that would make such code blocks more easily decipherable?


This question is about the underlying design decision, i.e. why it is useful to be able to write this code. See also Else clause on Python while statement for the specific question about what the syntax means.

Advertisement

Answer

It’s a strange construct even to seasoned Python coders. When used in conjunction with for-loops it basically means “find some item in the iterable, else if none was found do …”. As in:

found_obj = None
for obj in objects:
    if obj.key == search_key:
        found_obj = obj
        break
else:
    print('No object found.')

But anytime you see this construct, a better alternative is to either encapsulate the search in a function:

def find_obj(search_key):
    for obj in objects:
        if obj.key == search_key:
            return obj

Or use a list comprehension:

matching_objs = [o for o in objects if o.key == search_key]
if matching_objs:
    print('Found {}'.format(matching_objs[0]))
else:
    print('No object found.')

It is not semantically equivalent to the other two versions, but works good enough in non-performance critical code where it doesn’t matter whether you iterate the whole list or not. Others may disagree, but I personally would avoid ever using the for-else or while-else blocks in production code.

See also [Python-ideas] Summary of for…else threads

Advertisement