# Understanding while...else...

Terry Reedy tjreedy at udel.edu
Tue Jan 22 18:44:05 CET 2013

```Several people have trouble understanding Python's while-else and
for-else constructs. It is actually quite simple if one starts with
if-else, which few have any trouble with.

if n > 0:
n -= 1
else:
n = None

The else clause is executed if and when the condition is false. (That
the code is useless is not the point here.) Now use pseudo-Python label
and goto statements to repeatedly decrement n

label: check
if n > 0:
n -= 1
goto: check
else:
n = None

The else clause is executed if and when the condition is false. (I am
aware that the above will always set n to None if it terminates normally
and that something more is needed to do anything useful, but this is not
the point here.) Now use a real Python while statement to do the *same
thing*.

while n > 0:
n -= 1
else:
n = None

The else clause is executed if and when the condition is false. This is
the same as with the non-problematical if statement! To see that the
pseudo-Python is the 'correct' expansion, we can look at the
disassembled CPython byte code.

from dis import dis
dis('if n > 0: n -= 1\nelse: n = None')
dis('while n > 0: n -= 1\nelse: n = None')

produces

6 COMPARE_OP               4 (>)
9 POP_JUMP_IF_FALSE       25
18 INPLACE_SUBTRACT
19 STORE_NAME               0 (n)
22 JUMP_FORWARD             6 (to 31)

2     >>   25 LOAD_CONST               2 (None)
28 STORE_NAME               0 (n)
34 RETURN_VALUE

1           0 SETUP_LOOP              32 (to 35)
9 COMPARE_OP               4 (>)
12 POP_JUMP_IF_FALSE       28
21 INPLACE_SUBTRACT
22 STORE_NAME               0 (n)
25 JUMP_ABSOLUTE            3
>>   28 POP_BLOCK

32 STORE_NAME               0 (n)
38 RETURN_VALUE

The while loop code adds SETUP_LOOP to set up the context to handle
continue and break statements. It also add POP_BLOCK after the while
block. I presume this disables the loop context. Most importantly for
this discussion, JUMP_FORWARD (past the else block), which is implicit
in if-else statements, changes to JUMP_ABSOLUTE (to the condition test),
which is implicit in while statements and explicit in the pseudo-Python
expansion. Everything else is the same -- in particular the
POP_JUMP_IF_FALSE, after the condition test, which in both cases jumps
to the else block. So in both statements, the else block is executed if
and when the condition is false.

As for for-else statements, a for loop is basically a specialized while
loop plus assignment. The implicit while condition is that the iterable
has another item to process. So the else clause executes if and when
that condition is false, when iter(iterable) is exhausted.

--
Terry Jan Reedy

```