for what are for/while else clauses

Alex Martelli aleax at aleax.it
Mon Nov 17 07:34:09 EST 2003


Fredrik Lundh wrote:

> Alex Martelli wrote:
> 
>> > in every single case, it means "run once, if and only if the
>> > controlling condition is false".
>>
>> I'm not sure what you mean by "the controlling condition" in this case.
> 
> the condition that controls if the conditional part of the statement
> is executed.  from what I can tell, that's the usual definition.

We agree that it is the usual definition.  We appear to disagree that
focusing on that condition is a sensible way to present (e.g.) the way
while/else works.  E.g., consider:


>>> while avalue < another:
...     print avalue,
...     avalue += 1
... else:
...     print 'else here'
...

versus

>>> while avalue < another:
...     print avalue,
...     avalue += 1
...     if something(avalue, another): break
... else:
...     print 'else here'
...

When somebody else "will the else clause execute", I would answer
(for the first case) "yes [if the loop ever terminates]" -- and for
the second case, "if and only if the break does not execute [i.e.,
if the 'something' test is never satisfied while the controlling
condition holds]".

In the first case, it would make no difference whatsoever to
recode the loop as:

while avalue < another:
    print avalue,
    avalue += 1
print 'foo here'

Again, "foo here" gets printed (as long as the loop ever terminates).

But in the second case, where a guarded 'break' is involved, the
transliteration is not feasible (you'd have to add a 'flag' variable
in order to remove the 'else' and keep the same semantics).

It seems misleading to me to focus on the controlling condition, i.e.,
on whether "avalue < another" is still true, or not.  In the second
version of the loop it may perfectly well be true that the controlling
condition is false when the predicate 'something' is satisfied --
nevertheless, if the predicate is satisfied and thus the break
executes, the "else" clause does not execute.


>> In a for/else or while/else construct, the only way to make your
>> assertion true is to define "the controlling condition" as "a break
>> [or return] interrupted the for or while loop [or an exception was
>> propagated]" -- basically (quibbles on returns and exceptions apart)
>> just what I said about "no break was executed".
> 
> for a while-statement, the controlling condition is the test at
> the top.
> 
> for a for loop, the condition is "is there another item" (to quote the
> language reference: "When the items are exhausted (which is imme-
> diately when the sequence is empty) ... the loop terminates.".
> 
> for a try-except clause, the condition is "did the suite raise an
> exception".
> 
>> the fact that the 'controlling condition' is "a break statement
>> has executed"
> 
> that's not how it works.

In practice, it is (for both while and for, not for try; and net of
the already-interpolated distinguos about returns and exceptions).

When there is no 'break' in the loop's body, the 'else' clause is
useless: the body of the else clause would execute under exactly the
same conditions (i.e., if the loop ever terminates normally, w/o
return or exceptions) if the same statements were placed right after
the loop's end, rather than in an 'else' clause.  The only practical
reason to ever have an 'else' clause on a for or while is to do 
something different for a loop that terminates with a break, rather
than terminating "normally".  Focusing on the 'break' being present
and executing therefore seems more practical to me, than focusing on
the "controlling condition" (which may be false without this fact
causing the 'else' clause to execute -- if a break intervenes).


Alex





More information about the Python-list mailing list