[Python-ideas] Nudging beginners towards a more accurate mental model for loop else clauses
steve at pearwood.info
Sat Jun 9 19:49:43 CEST 2012
Devin Jeanpierre wrote:
> On Fri, Jun 8, 2012 at 10:31 PM, Steven D'Aprano <steve at pearwood.info> wrote:
>> Why is it misleading? It is *incomplete* insofar as it assumes the reader
>> understands that (in the absence of try...finally) a return or raise will
>> immediately exit the current function regardless of where in the function
>> that return/raise happens to be. I think that's a fair assumption to make.
> How can the reader understand that, when the reader doesn't know that
> return or raise exist yet? The assumption that the reader understands
> basic Python is unreasonable. This is the tutorial.
If the reader doesn't know that return or raise exist, they are hardly going
to draw conclusions about the behaviour of for/else when a return or raise is
If they do know about return and raise, they should understand that return and
raise skip everything, not just for/else.
> As I understand the objection, it is misleading in that it puts the
> focus on the wrong thing. It says "it's skipped by a break", as if
> that were special. It's skipped by a lot of things that aren't
> mentioned, the really interesting thing is when it _isn't_ skipped,
> which is glossed over.
I don't think it is glossed over at all. You cut out my quote of Yuval's
description, here it is again:
Loop statements may have an else clause; it is executed immediately
after the loop but is skipped if the loop was terminated by a break
The "really interesting thing" is the first thing about the else clause
mentioned: it is executed immediately after the loop.
The break statement *really is special* and deserves to be singled out for
mention. The break statement is the only way to exit the *entire* for-loop
construct (including the else) without exiting the entire function, or halting
> It is implied that this happens whenever it is
> exited by anything other than break, but of course that isn't true,
I strongly disagree that it implies anything of the sort. We're should assume
the readers are beginners, but not idiots.
Ignoring try/finally blocks, which are special, we can assume that the reader
has (or will have once they actually learn about functions and exceptions) a
correct understanding of the behaviour of return and raise.
- If the loop is exited by a return, *nothing* following the return is
executed. That includes the else block.
- If execution is halted by an exception (including raise), *nothing*
following the exception is executed. That includes the else block.
- If execution is halted by an external event that halts or interrupts the
Python process, *nothing* following executes. That includes the else block.
- If the loop never completes, *nothing* following the loop executes. That
includes the else block.
To continue the analogy with the "Red Dwarf" quote I made earlier:
"What about assignments after the loop?"
"No, they aren't executed. Nothing is executed."
"Well what about print statements?"
"No Dave, print statements aren't executed. Nothing is executed."
"How about the len() function?"
"No Dave, nothing is executed."
"What, not even the else clause?"
Unless we think that the average beginner to Python is as dumb as Dave Lister
from Red Dwarf, I don't think we need worry that they will imagine that
for/else blocks behave like try/finally.
Somehow we've gone from trying to fix an actual, real-life problem where
people assume that the else block executes if the loop sequence is empty, to
arguing how best to solve the entirely hypothetical problem that people might
imagine that else blocks have the special behaviour of try/finally.
More information about the Python-ideas