[Python-ideas] SyntaxWarning for for/while/else without break or return?
Steven D'Aprano
steve at pearwood.info
Fri Oct 9 04:10:01 CEST 2009
On Thu, 8 Oct 2009 07:57:38 pm Stefan Rank wrote:
> Hi,
>
> a suggestion/question related to the discussion about renaming
> for/else and while/else:
> Is it easy to generate a SyntaxWarning if you use these constructs
> without a break or return statement in the loop? AFAICS, any such
> usage would be either wrong or unnecessary. (right?)
-1 on such a warning. This sort of check belongs in PyLint or
equivalent, there is no need to complicate the compiler and make it
part of the language.
The compiler should be nicely lean and simple and not try to guess what
the user's intention is. for...else with no break is legal code, if
there's no break inside it, it is still legal code.
> This would both help prevent wrong usage because of a false intuition
> and, if adequately and prominently documented, would help those
> interested in learning about for/else while/else.
>
> Easily doable? Maybe even make it a SyntaxError?
-1000 on making it a SyntaxError. SyntaxErrors are for things which are
WRONG, not for things which are unnecessary or redundant or pointless.
Should this be prohibited too?
for x in seq:
if 0: break
else:
print "whatever"
What happens when the break is under a __debug__ test? The same source
compiles to two different byte-codes, one of which has break, the other
doesn't. Given this:
code = compile("""for x in seq:
if __debug__: break
else:
print "no break"
""", '', 'exec')
this is the byte-code you get running normally:
>>> dis.dis(code)
1 0 SETUP_LOOP 20 (to 23)
3 LOAD_NAME 0 (seq)
6 GET_ITER
>> 7 FOR_ITER 7 (to 17)
10 STORE_NAME 1 (x)
2 13 BREAK_LOOP
14 JUMP_ABSOLUTE 7
>> 17 POP_BLOCK
4 18 LOAD_CONST 0 ('no break')
21 PRINT_ITEM
22 PRINT_NEWLINE
>> 23 LOAD_CONST 1 (None)
26 RETURN_VALUE
and this is what you get running under python -O:
>>> dis.dis(code)
1 0 SETUP_LOOP 19 (to 22)
3 LOAD_NAME 0 (seq)
6 GET_ITER
>> 7 FOR_ITER 6 (to 16)
10 STORE_NAME 1 (x)
2 13 JUMP_ABSOLUTE 7
>> 16 POP_BLOCK
4 17 LOAD_CONST 0 ('no break')
20 PRINT_ITEM
21 PRINT_NEWLINE
>> 22 LOAD_CONST 1 (None)
25 RETURN_VALUE
No break in the second case. So now we have choices:
* Code which runs fine normally becomes a SyntaxError when running
with -O.
* for...else does not require a break when running with -O, but does
require it without -O.
* We pile complication on top of complication and make an explicit
exception for tests like if __debug__: break -- which means that we
still have for loops with no break that run perfectly fine!
* Stop optimizing if __debug__ tests.
All four of these alternatives are unacceptable.
--
Steven D'Aprano
More information about the Python-ideas
mailing list