Yes, thank you, I know that global variables are "evil". I don't care when I'm writing a throw-away program.
>>> x=0
>>> def f():
... x+=3
... print x
...
>>> f()
Traceback (most recent call last):
File "", line 1, in ?
File "", line 2, in f
UnboundLocalError: local variable 'x' referenced before assignment
My biggest objection to python while I was learning it was strange and unintuitive rule about scoping. And even now, when I'm pretty experienced in Python, I get bitten by it sometimes. Here's how to fix the upper piece of code: add
global x
just before the assignment addition. Strangely, the following piece of code works:Personally, I think that this is both unexpected and broken behaviour. This is not how lexical scoping (present in all modern programming languages) works. And the more I follow on the python development, the more hackish it is becoming.
>>> def g():
... print x
...
>>> g()
0
If you want a nice, small, and elegant language to embed in your application for scripting, take a look at Lua.
3 comments:
You obviously have wrong perception of Python scoping rules.
x = 0
def f():
print x
When you call f(), the interpreter creates new namespace for local variables. When you try to print ‘x’, the interpreter looks at that local namespace for variable x definition. As it cannot find it there, it looks at __parent__ object namespace. Interpreter finds that ‘x’ is defined[*] in that namespace so it prints it’s value.
x = 0
def f():
x += 3
print x
First, local namespace is created. When you try to add number 3 to variable ‘x’, the interpreter expects that ‘x’ is defined in local namespace but it is not. You must use ‘global’ keyword here to instruct interpreter to look at __parent__ namespace.
[*] Note that word ‘definition’ has no meaning in Python as in other languages
Actually, I have a wrong perception of +=. I read x+=3 the equivalent of x=x+3.
Now, following your description the x on the RHS of x=x+3 should be looked up in the parent scope (where it is defined as 0), and the result assigned to either the global x (the "expected" thing to do) or the new local copy of x (the "unexpected" thing to do).
So, can you explain in what fundamental way is x=x+3 different from print x or, even better example, y=x+3? In all cases the RHS is fully defined, however in the x=x+3 case the interpreter complains.
The only explanation that I can find is that, immediately upon entry to f, the interpreter knows ALL local variables that are used in f so binds them all to uninitialized values just after the opening : of the function definition.
In any case, I think that this is broken behaviour that doesn't deserve the name of nested scopes or static scoping.
zvrba: I think your last interpretation is correct, and I don't think it is that outlandish.
In python,
var = expression
is a definition of a local variable. Python could have had us writing something like:
define var = expression
for the first assignment to a variable, but I think I'd rather have the current, compact notation.
It isn't hard to see if a variable is being defined, just look if it's being assigned (whether through = or +=).
Right?
Post a Comment