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/

Reply via email to