Reputation: 331
I've come across some very odd handling of global variables in Python. I was hoping someone can explain and justify these surprises!
A) This code prints 10 as expected:
def func():
print(a)
a = 10
func()
B) This code throws an exception about referencing a too early:
def func():
print(a)
a += 1
a = 10
func()
C) But this code prints [10] as expected:
def func():
print(a)
a.append(1)
a = [10]
func()
So I can gather that the type of a
changes its scope and additionally later statements that haven't even been reached yet change how a
is seen. I know I can use global a
at the start of the function but it's rather verbose.
Can anyone tell me what rules Python is using to handle its bizarre scoping?
Upvotes: 3
Views: 197
Reputation: 16905
Basically, there are two rules:
You can change the behavior of #2, however:
global my_module_variable
. When you now write to my_module_variable
, Python will not create a local variable.nonlocal my_non_local_variable
to have it refer to the variable in the nearest enclosing scope.B) You are using +=
: You are trying to write to the variable. So rule number 2 is in effect, it will write to a variable in the current scope. However, it also has to read from it (print(a)
), but the variable does not yet have a value, because you haven't written to it before. Python does not allow you to mix rule 1.
and rule 2.
in a function.
If you wanted func()
to work on the a = 10
variable, you could change your code like this:
>>>> def func()
global a
print(a)
a += 1
>>>> a = 10
>>>> func()
10
>>>> func()
11
Upvotes: 4
Reputation: 798436
The second instance rebinds a
, so the compiler generates a local access for it. The other two only read a
, and so normal global scope searching is performed.
Upvotes: 5