[Python-ideas] SyntaxWarning for for/while/else without break or return?

Nick Coghlan ncoghlan at gmail.com
Sat Oct 10 13:22:11 CEST 2009

alex23 wrote:
> Masklinn <maskl... at masklinn.net> wrote:
>> The point of a warning is very much that the code works and is legal,  
>> but *in most case* is not what people would want. If it's what you  
>> want, you're free to go ahead and keep the code as is, ignoring the  
>> warning (or even filtering it out).
> You could make the same case for issuing a warning every time someone
> uses a mutable object as a default value in a function definition.
> This has _certainly_ caused a lot more confusion than the loop-else
> construct. But recourse to naive realism isn't a valid argument here;
> you're in effect punishing those who have taken their time to
> familiarise themselves with the language to spare those who haven't
> from ever having to do so.
> The effort should be in _learning_ the language, not in continually
> bypassing the training wheels.

We don't warn about mutable default arguments because in a lot of cases
the compiler doesn't know if the default argument is mutable or not, and
there are multiple well-established legitimate use cases that look
identical to noobish mistakes. Warning about for-else usage without
break is an entirely different scenario.

The comparison would hold water if we were proposing to issue a warning
for *any* use of for-else. We aren't - we're only proposing to issue it
for cases where the lack of a break statement suggests that the
programmer has misunderstood what the clause is for. Will that give the
occasional false positive due to code that is in the process of being
modified? Yeah, of course it will, otherwise I'd be proposing a
SyntaxError. Are those occasional false positives worth the benefit of
fewer buggy programs due to misunderstandings of the for/break/else
construct? In my opinion, yes.

For the record, there are three cases (not counting Py3k warnings) where
we currently issue syntax warnings (but generate valid code anyway).

1. Using "import *" at function level (as it disables local variable

>>> def f():
...   from sys import *
...   print version
...   print "version" in locals()
<stdin>:1: SyntaxWarning: import * only allowed at module level
>>> f()
2.5.2 (r252:60911, Jul 22 2009, 15:35:03)
[GCC 4.2.4 (Ubuntu 4.2.4-1ubuntu3)]

2. Referencing a global variable before declaring it as such:

>>> def f():
...   print x
...   global x
<stdin>:3: SyntaxWarning: name 'x' is used prior to global declaration
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
NameError: global name 'x' is not defined

3. Assigning to a global variable before declaring it as such:
>>> def f():
...   x = 1
...   global x
<stdin>:3: SyntaxWarning: name 'x' is assigned to before global declaration
>>> f()
>>> x

All 3 could easily be left to pylint/pychecker style tools, but were
deemed worthy of being warned about by the compiler itself.

Keep in mind that using a pylint/pychecker style tool at all is a
comparatively advanced Python technique. For cases like this where
misunderstandings are prevalent amongst both experienced and novice
Pythoneers, getting the compiler itself to offer a helping hand still
strikes me as a good idea.


Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list