1

I am confused with the python's design of global variables, it seems quite different for a normal global variable and a global list, consider the following code:

global_list = []
global_var = 0


def foo():
    for i in range(10):
        global global_var  # without this, error occurs
        global_var += 1
        global global_list  # without this, fine!
        global_list.append(i)


foo()
print(global_list)
print(global_var)

The code is quite self-explained, I would like to know why this is the case, what is the logic behind that. Besides, I've also tested a dictionary, it behaves like a list. What about other stuff, such as a class instance or something...

an offer can't refuse
  • 4,245
  • 5
  • 30
  • 50

1 Answers1

3

From the Programming FAQs:

In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a value anywhere within the function’s body, it’s assumed to be a local unless explicitly declared as global.

When you write:

global_var += 1

You are assigning a value to the name global_var after you have already referenced the global version The += construct needs to read the global then reassign to it — it's equivalent to:

global_var = global_var + 1
^            ^
|            |--global reference
|- local assignment

According to the above rule, this would make it a local variable unless declared global but you've already referenced the global.

When you write:

global_list.append(i)

You are not assigning a new value to the name global_list. global_list still points to the same array, the same thing happens with a dictionary. You would need to declare global global_list if you tried to reassign with something like:

global_list = global_list + [i]
Mark
  • 90,562
  • 7
  • 108
  • 148
  • what about a user declared instance. – an offer can't refuse Jun 20 '19 at 15:33
  • 1
    It doesn't really matter what the value is @喵喵是我的猫猫. What matters is whether or not you are reassigning the name (i.e. using `=`). If you can alter a user instance in-place without reassigning the name binding you don't need the global. Since things like numbers are immutable, you can't really change them without a reassignment. – Mark Jun 20 '19 at 15:34
  • In your answer, `According to the above rule, this would make it a local variable unless declared global but you've already referenced the global.`, if I don't declare it as global, this statement would be a wrong one, instead of making it a local variable. – an offer can't refuse Jun 20 '19 at 15:38
  • If you don't declare it as global and you write `global_var = global_var + 1` You are assigning a local variable with `global_var =`, but trying to read a global with `global_var + 1`. Python evaluates the right hand side first and finds the global variable, but then it's not clear what to do in the assignment on the left-hand side. – Mark Jun 20 '19 at 15:46
  • Even if I write `global_var = global_var + 1 `, the code is still a wrong one in my case(python 3.64): `UnboundLocalError: local variable 'global_var' referenced before assignment ` – an offer can't refuse Jun 20 '19 at 20:54