How can I make sense of the `else` clause of Python loops?
An if
statement runs its else
clause if its condition evaluates to false.
Identically, a while
loop runs the else clause if its condition evaluates to false.
This rule matches the behavior you described:
- In normal execution, the while loop repeatedly runs until the condition evaluates to false, and therefore naturally exiting the loop runs the else clause.
- When you execute a
break
statement, you exit out of the loop without evaluating the condition, so the condition cannot evaluate to false and you never run the else clause. - When you execute a
continue
statement, you evaluate the condition again, and do exactly what you normally would at the beginning of a loop iteration. So, if the condition is true, you keep looping, but if it is false you run the else clause. - Other methods of exiting the loop, such as
return
, do not evaluate the condition and therefore do not run the else clause.
for
loops behave the same way. Just consider the condition as true if the iterator has more elements, or false otherwise.
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 exception
, no break
, 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 else
block:
for items in basket:
if isinstance(item, Egg):
break
else:
print("No eggs in basket")
A continue
does not hijack control from for
, so control will proceed to the else
after the for
is exhausted.
When does an if
execute an else
? When its condition is false. It is exactly the same for the while
/else
. So you can think of while
/else
as just an if
that keeps running its true condition until it evaluates false. A break
doesn't change that. It just jumps out of the containing loop with no evaluation. The else
is only executed if evaluating the if
/while
condition is false.
The for
is similar, except its false condition is exhausting its iterator.
continue
and break
don't execute else
. That isn't their function. The break
exits the containing loop. The continue
goes back to the top of the containing loop, where the loop condition is evaluated. It is the act of evaluating if
/while
to false (or for
has no more items) that executes else
and no other way.
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:
...
The else
clause will not be executed if there is a return
because 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 break
.
try/else
is similar:
try:
...
except:
...
if there was an exception:
pass
else:
...
If you think of your loops as a structure similar to this (somewhat pseudo-code):
loop:
if condition then
... //execute body
goto loop
else
...
it might make a little bit more sense. A loop is essentially just an if
statement that is repeated until the condition is false
. And this is the important point. The loop checks its condition and sees that it's false
, thus executes the else
(just like a normal if/else
) and then the loop is done.
So notice that the else
only get's executed when the condition is checked. That means that if you exit the body of the loop in the middle of execution with for example a return
or a break
, since the condition is not checked again, the else
case won't be executed.
A continue
on the other hand stops the current execution and then jumps back to check the condition of the loop again, which is why the else
can be reached in this scenario.