scope of function parameters

Chris Angelico rosuav at gmail.com
Sun May 29 15:20:51 EDT 2011


On Mon, May 30, 2011 at 4:53 AM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> UnboundLocalError is a subclass of NameError, so it will still be caught
> by try...except NameError.
>
> If you're crazy enough to be catching NameError :)

Ah okay. So it is still NameError, it just doesn't look like one.

> While UnboundLocalError is jargon, and not the easiest error message to
> comprehend, at least it confuses in a different way :)

I have nothing against jargon, and specific errors are better than
generic ones (imagine if every error were thrown as Exception with a
string parameter... oh wait, that's what string exceptions are).

It still seems a little odd that a subsequent line can affect this
one. But Python's mostly doing what would be expected of it; the worst
I can come up with is this:

def f():
  print(foo) # reference a global
  ...
  for foo in bar: # variable only used in loop
    pass

If you're used to C++ and declaring variables inside a for loop eg
"for (int i=0;i<10;++i)", you might not concern yourself with the fact
that 'foo' is masking a global; it's not an issue, because you don't
need that global inside that loop, right? And it would be fine, except
that that global IS used somewhere else in the function. It'd be a bit
confusing to get the UnboundLocalError up on the print(foo) line (the
one that's meant to be using the global), since that line isn't wrong;
and the "obvious fix", adding an explicit "global foo" to the top of
the function, would be worse (because it would mean that the for loop
overwrites the global).

This is why I would prefer to declare variables. The Zen of Python
says that explicit is better than implicit, but in this instance,
Python goes for DWIM, guessing whether you meant global or local. It
guesses fairly well, though.

Chris Angelico



More information about the Python-list mailing list