Using Global Variables inside a Nested Function in Python

Viewed 3079

I read this code (given below) and my understanding was that, if a variable is declared global inside a function and if it is modified then it's value will change permanently.

x = 15
def change(): 
    global x 
    x = x + 5
    print("Value of x inside a function :", x) 
change() 
print("Value of x outside a function :", x)  

Output:

Value of x inside a function : 20
Value of x outside a function : 20

But the code below shows a different output. How is it that the value of x does not change inside the print("After making change: ", x) and still remains 15

def add(): 
    x = 15
    
    def change(): 
        global x 
        x = 20
    print("Before making changes: ", x) 
    print("Making change") 
    change() 
    print("After making change: ", x) 

add() 
print("value of x",x) 

Output:

Before making changes:  15
Making change
After making change:  15
value of x 20
3 Answers

In add, x is not a global variable; it's local to add. You either need to make it global as well, so that add and change are referring to the same variable

def add(): 
    global x
    x = 15
    
    def change(): 
        global x 
        x = 20
    print("Before making changes: ", x) 
    print("Making change") 
    change() 
    print("After making change: ", x) 

add() 
print("value of x",x)

or you need to declare x in change as nonlocal, rather than global.

def add(): 
    x = 15
    
    def change(): 
        nonlocal x 
        x = 20
    print("Before making changes: ", x) 
    print("Making change") 
    change() 
    print("After making change: ", x) 

add() 
print("value of x",x)

Inside the function add the variable x is present in the enclosing scope and not the global scope that's why your variable x won't change even if you use the global keyword.
To change this x you need nonlocal keyword which applies to the variables present in the enclosing scope.

The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals.


# global scope
x = 0  


def add():
    # enclosing scope
    x = 15

    def change():
        nonlocal x
        x = 20

    print("Before making changes: ", x)
    print("Making change")
    change()
    print("After making change: ", x)


add()
print("value of x", x)  # this x is global variable

Output:

Before making changes:  15
Making change
After making change:  20
value of x 0

when you define global x in change() function, nested in add() function; it defines a main global x variable which is different from local x = 15 at the beginning of the add() function. when you print x before and after calling change(), you actually use local x = 15 at the beginning of add() function, but final print after calling add() will use defined global x which defined in main scope and has the value of 20

more explanation

Related