On Sun, Mar 05, 2017 at 01:17:31PM +1000, Nick Coghlan wrote:

> I forget where it came up, but I seem to recall Guido saying that if he
> were designing Python today, he wouldn't include the "else:" clause on
> loops, since it inevitably confuses folks the first time they see it.

Heh, if we exclude all features that confuse people the first time they 
see it, we'd have to remove threads, Unicode, floating point maths, 
calls to external processes, anything OS-dependent, metaclasses, 
classes, ... :-)


It took me the longest time to realise that the "else" clause didn't 
*only* run when the loop sequence is empty. That is, I expected that 
given:

for x in random.choice(["", "a"]):  # either empty, or a single item
    print("run the loop body")
else:
    print("loop sequence is empty")

That's because it *seems* to work that way, if you do insufficient 
testing:

for x in []:
    raise ValueError  # dead code is not executed
else:
    print("loop sequence is empty")



It is my belief that the problem here is not the else clause itself, but 
that the name used is misleading. I've seen people other than 
myself conclude that it means:

run the for-loop over the sequence
otherwise the sequence is empty, run the ELSE block

I've seen people think that it means:

set break_seen flag to false
run the for-loop
if break is executed, set the break_seen flat to true then break
if break_seen is false, run the "ELSE NOT BREAK" clause

and consequently ask how they can access the break_seen flag for 
themselves. Presumably they want to write something like:

run the for-loop
if break_seen is true, do this
else (break_seen is false) do that

I think that the name "else" here is a "misunderstanding magnet", it 
leads people to misunderstand the nature of the clause and its 
implications.

For example, I bet that right now there are people reading this and 
nodding along with me and thinking "maybe we should rename it something 
more explicit, like "else if no break", completely oblivious to the fact 
that `break` is NOT the only way to avoid running the `else` clause.

I believe that the name should have been "then", not "else". It 
describes what the code does:

run the for-block
THEN run the "else" block

There's no flag to be tested, and the "else" block simply runs once, 
after the for-loop, regardless of whether the for-loop runs once or ten 
times or zero times (empty sequence). To avoid running the "else" 
("then") block, you have to exit the entire block of code using:

- break
- return
- raise

which will all transfer execution past the end of the for...else 
(for...then) compound statement.

Since I realised that the else block merely runs directly after the for, 
I've never had any problem with the concept. `break` merely jumps past 
the for...else block, just as `return` exits the function and `raise` 
triggers an exception which transfers execution to the surrounding 
`except` clause.



-- 
Steve
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to