On Sat, May 21, 2016 at 5:20 PM, Erik <pyt...@lucidity.plus.com> wrote: > On 20/05/16 01:06, Steven D'Aprano wrote: > >> In my experience, some people (including me) misunderstand "for...else" to >> mean that the else block runs if the for block *doesn't*. It took me the >> longest time to understand why this didn't work as I expected: >> >> for x in seq: >> pass >> else: >> print("seq is empty") > > > So why don't we consider if that should be a syntax error - "else" clause on > "for" loop with no "break" in its body? I know that doesn't change your > fundamental mental model, but it's a hint that it's wrong :) > > As it's backwards-incompatible, it could be introduced using a __future__ > import (a precedent is 'generators' and the "yield" keyword back in the day) > which those who would like the new check could add to the top of their > sources. > > But also, as you say, any instances of that construct in the wild is almost > certainly a bug, so it would be good to be able to test code using a > command-line or similar switch to turn on the behaviour by default for > testing existing bodies of code. > > I notice that pylint complains about this (as a warning). Is there any > reason why this should _not_ just be considered an error and be done with > it?
Because it's not the language parser's job to decide what's "sensible" and what's "not sensible". That's a linter's job. Some things fundamentally can't work, but others work fine and might just be not-very-useful - for example: def f(x): x if x <= 2 else x * f(x-1) This is syntactically-legal Python code, but it probably isn't doing what you want it to (in Python, a bare final expression does NOT become the function's return value, although that does happen in other languages). A linter should look at this and give a warning (even if the else part has side effects, the first part can't, and the condition shouldn't), but the language will happily evaluate it (this example from CPython 3.6): >>> dis.dis(f) 2 0 LOAD_FAST 0 (x) 3 LOAD_CONST 1 (2) 6 COMPARE_OP 1 (<=) 9 POP_JUMP_IF_FALSE 18 12 LOAD_FAST 0 (x) 15 JUMP_FORWARD 17 (to 35) >> 18 LOAD_FAST 0 (x) 21 LOAD_GLOBAL 0 (f) 24 LOAD_FAST 0 (x) 27 LOAD_CONST 2 (1) 30 BINARY_SUBTRACT 31 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 34 BINARY_MULTIPLY >> 35 POP_TOP 36 LOAD_CONST 0 (None) 39 RETURN_VALUE So, yes, this function might load up the value of x (position 12), then jump to 35 and discard that value, before unconditionally returning None. Not a problem. It's up to the linter, and ONLY the linter, to tell you about this. ChrisA -- https://mail.python.org/mailman/listinfo/python-list