Yes, it's the same in Python 3. For the most part this is desirable, if not entirely intuitive behavior. Perhaps you have to be Dutch. Many people may be familiar with hoisting (popularized by JavaScript?). It happens in Python, too, except that instead of having an undefined
value, Python just raises an UnboundLocalError
. Compare:
> // JavaScript example
> var x = 1;
> function foo() {
if (!x) { // x is declared locally below, so locally x is undefined
var x = 2;
}
return x;
}
> foo();
2
>>> # Everything else is Python 3
>>> x = 1
>>> def foo():
... if not x: # x is bound below, which constitutes declaring it as a local
... x = 2
... return x
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'x' referenced before assignment
So far Python's consistent, but there's a (troubling) workaround:
>>> def foo():
... if not 'x' in locals():
... x = 2
... return x
...
>>> foo()
2
That works, and we've been told
The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.
But doesn't locals()
give us all the local names? Evidently not. In fact, despite the previous statement, Python hints that the local symbol table can change in the description of the locals()
builtin:
Update and return a dictionary representing the current [emphasis mine] local symbol table.
I used to think the word current referred to the values, now I think it refers to the keys as well. But ultimately what I think this means is there's no way (short of dumping and parsing the source code for a frame) to enumerate all the names that are declared locally (which is not to say you can't use try/except UnboundLocalError to determine if a specific name is local.)
def foo():
# Some code, including bindings
del x, y, z # or any other local names
# From this point, is it programmatically knowable what names are local?
This, I think, is a fundamental difference between a language with implicit declarations and a language with explicit ones.