开发者

Python variable resolving

开发者 https://www.devze.com 2023-01-12 02:48 出处:网络
Given the following code: a = 0 def foo(): # global a a += 1 foo() When run, Python complains: UnboundLocalError: local variable \'a\' referenced before assignment

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消