Understanding while...else...

T

Terry Reedy

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.

Start with, for example

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

1 0 LOAD_NAME 0 (n)
3 LOAD_CONST 0 (0)
6 COMPARE_OP 4 (>)
9 POP_JUMP_IF_FALSE 25
12 LOAD_NAME 0 (n)
15 LOAD_CONST 1 (1)
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)6 LOAD_CONST 0 (0)
9 COMPARE_OP 4 (>)
12 POP_JUMP_IF_FALSE 28
15 LOAD_NAME 0 (n)
18 LOAD_CONST 1 (1)
21 INPLACE_SUBTRACT
22 STORE_NAME 0 (n)
25 JUMP_ABSOLUTE 3
2 29 LOAD_CONST 2 (None)
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top