Why does assigning to my global variables not work in Python?

PythonGlobal VariablesScope

Python Problem Overview


I'm having terrible trouble trying to understand python scoping rules.

With the following script:

a = 7

def printA():
   	print "Value of a is %d" % (a)

def setA(value):
	a = value
	print "Inside setA, a is now %d" %(a)
	

print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Gives the unexpected (to me) output of:

Before setA
Value of a is 7
Inside setA, a is now 42
After setA
Value of a is 7
Where I would expect the last printing of the value of a to be 42, not 7. What am I missing about Python's scope rules for the scoping of global variables?

Python Solutions


Solution 1 - Python

Global variables are special. If you try to assign to a variable a = value inside of a function, it creates a new local variable inside the function, even if there is a global variable with the same name. To instead access the global variable, add a global statement inside the function:

a = 7
def setA(value):
    global a   # declare a to be a global
    a = value  # this sets the global value of a

See also Naming and binding for a detailed explanation of Python's naming and binding rules.

Solution 2 - Python

The trick to understanding this is that when you assign to a variable, using =, you also declare it as a local variable. So instead of changing the value of the global variable a, setA(value) actually sets a local variable (which happens to be called a) to the value passed in.

This becomes more obvious if you try to print the value of a at the start of setA(value) like so:

def setA(value):
    print "Before assignment, a is %d" % (a)
    a = value
    print "Inside setA, a is now %d" % (a)

If you try to run this Python will give you a helpful error:

Traceback (most recent call last):
File "scopeTest.py", line 14, in 
setA(42)
File "scopeTest.py", line 7, in setA
print "Before assignment, a is %d" % (a)
UnboundLocalError: local variable 'a' referenced before assignment
This tells us that Python has decided that the setA(value) function has a local variable called a, which is what you alter when you assign to it in the function. If you don't assign to a in the function (as with printA()) then Python uses the global variable A.

To mark a variable as global you need to use the global keyword in Python, in the scope that you want to use the global variable. In this case that is within the setA(value) function. So the script becomes:

a = 7

def printA():
	print "Value of a is %d" % (a)

def setA(value):
	global a
	a = value
	print "Inside setA, a is now %d" %(a)
	

print "Before setA"
printA()
setA(42)
print "After setA"
printA()

This one line addition tells Python that when you use the variable a in the setA(value) function that you are talking about the global variable, not a local variable.

Solution 3 - Python

inside the function,a is treated as a local variable,you need to define

> global a

inside the function before using it inside the method, even though you had defined it outside the method.

Solution 4 - Python

Python does not have a concept of variables as other languages. You have objects which are "somewhere" and you have references to these objects. = is used to assign these objects to references in the current namespace.

You create a name a in the namespace of the setA function which refers to the object to which value refers.

Solution 5 - Python

The execution of a function introduces a new symbol table used for the local variables of the function. More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names. Thus, global variables cannot be directly assigned a value within a function (unless named in a global statement), although they may be referenced.

Solution 6 - Python

Accepted answer here should be helpful:

> using global incorrectly. See Python reference. You should > declare variable without global and then inside the function when you > want to access global variable you declare it global yourvar

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFree WildebeestView Question on Stackoverflow
Solution 1 - PythonAdam RosenfieldView Answer on Stackoverflow
Solution 2 - PythonFree WildebeestView Answer on Stackoverflow
Solution 3 - PythonappusajeevView Answer on Stackoverflow
Solution 4 - PythonDasIchView Answer on Stackoverflow
Solution 5 - PythonNilesh JainView Answer on Stackoverflow
Solution 6 - PythonsocialView Answer on Stackoverflow