Python variable resolution

Given the following code:

a = 0 def foo(): # global a a += 1 foo() 

At startup, Python complains: UnboundLocalError: local variable 'a' referenced before assignment

However, when it's a dictionary ...

 a = {} def foo(): a['bar'] = 0 foo() 

The thing is working fine ...

Does anyone know why we can reference the second piece of code, but not the first?

+6
python
source share
4 answers

The difference is that in the first example, you assign a , which creates a new local name a , which hides global a .

In the second example, you are not assigning a , so global a .

This is described in the documentation .

Pythonโ€™s special quirk is that - if the global operator doesnโ€™t work, name assignments always go inside.

+2
source share

The question is one of the updates.

You cannot update a because it is not a variable in your local network. In-place update assignment operation is not updated a .

Interestingly, a = a + 1 also fails.

Python generates slightly optimized code for these statements. It uses the LOAD_FAST statement.

  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 using a on the left and right sides of the equal sign leads to this optimization.

However, you can access a because Python will look for local and global namespaces for you.

Since a not displayed on the left side of the assignment operator, another 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 
+1
source share

a += 1 equivalent to a = a + 1 . By assigning the variable a , it becomes local. The value you are trying to assign a + 1 fails because a is not yet bound.

0
source share

This is very common Python: if you assign a variable inside a function (like you, with += ), anywhere (not necessary, before using it in any other way), it does not use the global one. However, since what you are doing is effectively "a = a + 1", you are trying to access a (on the right side of the expression) before assigning it to it.

Try using global a at the beginning of your function (but be careful that you overwrite the global value of a ).

In your second example, you do not assign the variable a , but only to one of its elements. Therefore, the global dict a .

0
source share

All Articles