On 3/4/2017 10:17 PM, 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.
(Hence articles like mine that attempt to link it with try/except/else
rather than if/else).
The link needs to be done in two separate steps: if-else => while-else
=> for-else.
Step 1. The conceptual difference between an if-clause and a
while-clause is that an if-clause ends with an implied 'break' (jump
past the rest of the statement to the next statement) while a
while-clause ends with an implied 'continue' (jump back to the condition
test). In the CPython byte code, this difference is implemented by
JUMP_FORWARD versus JUMP_ABSOLUTE (backwards). (The byte code for a
while-clause also has two bookkeeping additions, SETUP_LOOP and POP_BLOCK.)
In both if-statements and while-statements, the else-clause is executed
if and when the condition is false. I wonder if having never
programming with with 'jump' or 'goto' makes this harder to understand.
I think our doc could better explain how if-statements and
while-statements are similar but different.
Step 2. A for-loop can be viewed as an initialized while-loop.
Kernighan and Ritchie make this explicit in The C Programming Language
(p. 56).
'''
The for statement
for (expr1; expr2; expr3)
statement
is equivalent to
expr1;
while (expr2) {
statement
expr3;
}
'''
For Python's more specialized for-loop, 'for target-list in iterable:
for-suite' can be paraphrased as 'while the iterator yields an object
(is not exhausted): do the assignment and suite'. An else-clause, if
present, is executed if and when the condition is false, when the
iterator is exhausted and raises StopIteration instead of yielding an
object. If while-else is understood and the implicit for condition is
understood, for-else is pretty straightforward.
Equivalent code, with an else-clause, is trickier than in C, without
for-else. I think the following is close. I think something like this
should be in the doc.
_it = iter(iterable)
_exhausted = False
while not _exhausted:
try:
_obj = next(_it)
except StopIteration:
_exhausted = True
continue
target-list = _obj
for-suite
else:
else-suite
Note 1: without the else-clause, _exhausted is not needed. The loop
could be 'while True' and the except clause could just be 'break'.
Note 2: _obj being assignment compatible with target list is NOT part of
the implicit while condition. For example,
for a,b in (1,2): print('for')
else: print('else')
prints nothing except the traceback for TypeError: 'int' object is not
iterable.
Note 3: C for typically assigns to the loop variable once before the
loop and and again at the end of each loop. Python for does the
assignment once at the top of the loop.
--
Terry Jan Reedy
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/