HiveBrain v1.2.0
Get Started
← Back to all entries
gotchapythonCritical

Why does python use 'else' after for and while loops?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
whywhilepythondoesafterelseandloopsforuse

Problem

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.

Solution

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

Code Snippets

found_obj = None
for obj in objects:
    if obj.key == search_key:
        found_obj = obj
        break
else:
    print('No object found.')
def find_obj(search_key):
    for obj in objects:
        if obj.key == search_key:
            return obj
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.')

Context

Stack Overflow Q#9979970, score: 427

Revisions (0)

No revisions yet.