How can I make sense of the `else` clause of Python loops?
Better to think of it this way: The
else block will always be executed if everything goes right in the preceding
for block such that it reaches exhaustion.
Right in this context will mean no
return. Any statement that hijacks control from
for will cause the
else block to be bypassed.
A common use case is found when searching for an item in an
iterable, for which the search is either called off when the item is found or a
"not found" flag is raised/printed via the following
for items in basket: if isinstance(item, Egg): break else: print("No eggs in basket")
continue does not hijack control from
for, so control will proceed to the
else after the
for is exhausted.
Many Python programmers are probably unaware that the syntax of
while loops and
for loops includes an optional
for val in iterable: do_something(val) else: clean_up()
The body of the
else clause is a good place for certain kinds of clean-up actions, and is executed on normal termination of the loop: I.e., exiting the loop with
break skips the
else clause; exiting after a
continue executes it. I know this only because I just looked it up (yet again), because I can never remember when the
else clause is executed.
Always? On "failure" of the loop, as the name suggests? On regular termination? Even if the loop is exited with
return? I can never be entirely sure without looking it up.
I blame my persisting uncertainty on the choice of keyword: I find
else incredibly unmnemonic for this semantics. My question is not "why is this keyword used for this purpose" (which I would probably vote to close, though only after reading the answers and comments), but how can I think about the
else keyword so that its semantics make sense, and I can therefore remember it?
I'm sure there was a fair amount of discussion about this, and I can imagine that the choice was made for consistency with the
else: clause (which I also have to look up), and with the goal of not adding to the list of Python's reserved words. Perhaps the reasons for choosing
else will clarify its function and make it more memorable, but I'm after connecting name to function, not after historical explanation per se.
The answers to this question, which my question was briefly closed as a duplicate of, contain a lot of interesting back story. My question has a different focus (how to connect the specific semantics of
else with the keyword choice), but I feel there should be a link to this question somewhere.
This is what it essentially means:
for/while ...: if ...: break if there was a break: pass else: ...
It's a nicer way of writing of this common pattern:
found = False for/while ...: if ...: found = True break if not found: ...
else clause will not be executed if there is a
return leaves the function, as it is meant to. The only exception to that which you may be thinking of is
finally, whose purpose is to be sure that it is always executed.
continue has nothing special to do with this matter. It causes the current iteration of the loop to end which may happen to end the entire loop, and clearly in that case the loop wasn't ended by a
try/else is similar:
try: ... except: ... if there was an exception: pass else: ...
My gotcha moment with the loop's
else clause was when I was watching a talk by Raymond Hettinger, who told a story about how he thought it should have been called
nobreak. Take a look at the following code, what do you think it would do?
for i in range(10): if test(i): break # ... work with i nobreak: print('Loop completed')
What would you guess it does? Well, the part that says
nobreak would only be executed if a
break statement wasn't hit in the loop.
Others have already explained the mechanics of
while/for...else, and the Python 3 language reference has the authoritative definition (see while and for), but here is my personal mnemonic, FWIW. I guess the key for me has been to break this down into two parts: one for understanding the meaning of the
else in relation to the loop conditional, and one for understanding loop control.
I find it's easiest to start by understanding
whileyou have more items, do stuff,
elseif you run out, do this
for...else mnemonic is basically the same:
forevery item, do stuff, but
elseif you run out, do this
In both cases, the
else part is only reached once there are no more items to process, and the last item has been processed in a regular manner (i.e. no
continue just goes back and sees if there are any more items. My mnemonic for these rules applies to both
returning, there's nothing
and when I say
continue, that's "loop back to start" for you
– with "loop back to start" meaning, obviously, the start of the loop where we check whether there are any more items in the iterable, so as far as the
else is concerned,
continue really plays no role at all.
The way I see it,
else: fires when you iterate past the end of the loop.
raise you don't iterate past the end of loop, you stop immeadiately, and thus the
else: block won't run. If you
continue you still iterate past the end of loop, since continue just skips to the next iteration. It doesn't stop the loop.
The way I think about it, the key is to consider the meaning of
continue rather than
The other keywords you mention break out of the loop (exit abnormally) whilst
continue does not, it just skips the remainder of the code block inside the loop. The fact that it can precede loop termination is incidental: the termination is actually done in the normal way by evaluation of the loop conditional expression.
Then you just need to remember that the
else clause is executed after normal loop termination.