Python variable resolving
Given the following code:
a = 0
def foo():
# global a
a += 1
foo()
When run, Python complains: UnboundLocalError: local variable 'a' referenced before assignment
However, when it's a dictionary...
a = {}
def foo():
a['bar'] = 0
foo()
The thing runs just fine...
An开发者_StackOverflow中文版yone know why we can reference a in the 2nd chunk of code, but not the 1st?
The difference is that in the first example you are assigning to a
which creates a new local name a
that hides the global a
.
In the second example you are not making an assignment to a
so the global a
is used.
This is covered in the documentation.
A special quirk of Python is that – if no global statement is in effect – assignments to names always go into the innermost scope.
The question is one of update.
You cannot update a
because it is not a variable in your function's local namespace. The update-in-place assignment operation fails to update a
in place.
Interestingly, a = a + 1
also fails.
Python generates slightly optimized code for these kind of statements. It uses a "LOAD_FAST" instruction.
2 0 LOAD_FAST 0 (a)
3 LOAD_CONST 1 (1)
6 INPLACE_ADD
7 STORE_FAST 0 (a)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
Note that the use of a
on left and right side of the equal sign leads to this optimization.
You can, however, access a
because Python will search local and global namespaces for you.
Since a
does not appear on the left side of an assignment statement, a different kind of access is used, "LOAD_GLOBAL".
2 0 LOAD_CONST 1 (0)
3 LOAD_GLOBAL 0 (a)
6 LOAD_CONST 2 ('bar')
9 STORE_SUBSCR
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
a += 1
is equivalent to a = a + 1
. By assigning to variable a
, it is made local. The value you attempt to assign a + 1
fails because a
hasn't been bound yet.
That's a very common Python gotcha: if you assign to a variable inside a function (as you do, with +=
), anywhere at all (not necessarily before you use it some other way), it doesn't use the global one. However, since what you're doing is effectively "a = a + 1", you're trying to access a
(on the right-hand side of the expression) before assigning to it.
Try using global a
at the beginning of your function (but beware that you'll overwrite the global a
value).
On your second example, you're not assigning the the variable a
, but only to one of its items. So the global dict a
is used.
精彩评论