Global, Local and Nonlocal variables in Python | by Tanu N Prabhu | Towards Data Science

First of all, I’m not the one on that image above. I’m just a benevolent writer who is here to talk about one of the most confusing concepts in Python programming “Global, Local and Nonlocal variables”. I know after reading the title you will be like “Why should I even worry about this”. Well, the answer is sometimes not knowing these teeny tiny itsy bitsy would cost you a lot. So without further ado, let’s get started.
In programming languages like C/C++, every time a variable is declared simultaneously a memory would be allocated this would allocation would completely depend on the variable type. Therefore, the programmers must specify the variable type while creating a variable. But luckily in Python, you don’t have to do that. Python doesn’t have a variable type declaration. Like pointers in C, variables in Python don’t store values legitimately; they work with references highlighting objects in memory.
The list of topics that would be covered in this article is given below:
Variables — A quick introduction
Global Variables — How to get rid of UnboundLocalError
Local Variables — How to get rid of NameError
Nonlocal Variables — When and how to use them
Also, before getting started I have to tell you one thing. The whole code of this article can be found in my GitHub Repository given below:
github.com
A variable is more likely a container to store the values. Now the values to be stored depends on the programmer whether to use integer, float, string or etc.
A Variable is like a box in the computer’s memory where you can store a single value. — Al Sweigart
Unlike in other programming languages, in Python, you need not declare any variables or initialize them. Please read this.
The general syntax to create a variable in Python is as shown below:
variable_name = value
The variable_name in Python can be short as sweet as a, b, x, y, ... or can be very informative such as age, height, name, student_name, covid, ...
Although it is recommended keeping a very descriptive variable name to improve the readability.
All set and done, there are some rules that you need to follow while naming a variable:
A variable name must start with a letter or the underscore character
A variable name cannot start with a number
A variable name can only contain alpha-numeric characters and underscores. For example, anything like this is valid: A-z, 0–9, and _
Variable names are case-sensitive (height, Height, and HEIGHT are three different variables names)
Below given is an example to properly initialize a value to a variable:
# This is a valid and good way to assign a value to a variable# Let's assign values to variables to calculate the area of a circlepi = 3.142            # I could have also used "math" library radius = 5            # Interger value for radiusarea_of_circle = 0    # Used to store the value of area of circlearea_of_circle = pi * (radius) ** 2        # Area = (PI * R^2)print("The area of the circle is: ", area_of_circle)
The output of the above code is given below:
The area of the circle is:  78.55
I believe just by seeing a picture or an image, the concepts can be understood more quickly. Below is the pictorial representation of a variable and it being stored in the memory.
In Python or any other programming languages, the definition of global variables remains the same, which is “A variable declared outside the function is called global function”. We can access a global variable inside or outside the function.
Let’s use the same example from above to understand the concept of accessing the variable inside and outside the function.
pi = 3.142       # I could have also used "math" library (math.pi)radius = 5       # Interger value for radiusdef circle():    area_of_circle = pi * (radius) ** 2    print("The area of the circle is: ",   area_of_circle)    circumference_of_circle = 2 * pi * radius# Accessing the global variables outside the functionprint("The circumference of the circle: ", circumference_of_circle)# Accessing the global variables inside the functioncircle()     
The output for the above code is given below:
The circumference of the circle:  31.419999999999998 The area of the circle is:  78.55
There you go this is the specialty of global variables. As seen in the above example I have used two common variables pi and radius to calculate the area of the circle which is declared inside a function and area of the circumference which is calculated outside the function. For both these calculations, we are using the same common variables.
Now let’s take the same old example and try to update the radius by 2 (multiply by 2)
pi = 3.142       # I could have also used "math" library (math.pi)radius = 5       # Interger value for radiusdef circle():    radius = radius * 2         # Update the radius by (x 2)    area_of_circle = pi * (radius) ** 2    print("The area of the circle is: ", area_of_circle)circle()     # Accessing the global variables inside the function
Now I know you might be like “there is no necessity” of this extra step radius = radius * 2 we can directly do this in the initial step by assigning the value to the radius as 10 i.e. radius = 10. I know but I am trying to introduce a concept here. Please bear with me.
As seen in the above code, if you try to update the radius and then execute this piece of code you will be surprised. Don’t be excited and say “I did it” because you didn’t, rather you will be prompted by an error called UnboundLocalError. More likely the error looks like this.
UnboundLocalError: local variable 'radius' referenced before assignment
The reason for this error is that the variable radius is local and it cannot be updated as above. Here, you can make it a global variable. Now how to do it. Please see the below code snippet.
pi = 3.142       # I could have also used "math" library (math.pi)radius = 5       # Interger value for radiusdef circle():    global radius               # Making raduis a global variable    radius = radius * 2         # Update the radius by (x 2)    area_of_circle = pi * (radius) ** 2    print("The area of the circle is: ", area_of_circle)circle()     
Now when you execute the code, it executes with no problem. Because now it explicitly declared as a global variable. The output of the above code is given below:
The area of the circle is:  314.2
Time to test your knowledge in the long run. Two years back there was this one question asked in Stack Overflow about UnboundLocalError. The form is now closed for answers because there are already tons of answers present. You can hop in there and try to answer it and understand it more clearly.
In Python or any other programming languages, the definition of local variables remains the same, which is “A variable declared inside the function is called local function”. We can access a local variable inside but not outside the function.
We use the local variables inside a function and not try to access them outside those functions. Hence the name local. But the good part is we can access those variables within the functions itself.
def circle():    pi = 3.142    # I could have also used "math" library (math.pi)    radius = 5    # Interger value for radius    area_of_circle = pi * (radius) ** 2    print("The area of the circle is: ",   area_of_circle)    circumference_of_circle = 2 * pi * radius# Accessing the global variables inside the functioncircle()
The output of the above code is:
The area of the circle is:  78.55
There you go this is the specialty of local variables. As seen in the above example I have used two common variables pi and radius to calculate the area of the circle which is declared inside a function. So accessing these variables will not create any problem. But what happens if we try to access them outside the function. See the next section below.
Let’s use the same example from above and access the variables declared inside the function:
def circle():    pi = 3.142    # I could have also used "math" library (math.pi)    radius = 5    # Interger value for radius        area_of_circle = pi * (radius) ** 2    print("The area of the circle is: ",   area_of_circle)    circumference_of_circle = 2 * pi * radius# Accessing the global variables outside the functionprint("The circumference of the circle: ", circumference_of_circle)# Accessing the global variables inside the functioncircle()
When you execute the above code, you will be prompted by a NameError. More likely the error looks like this
NameError: name 'pi' is not defined
The reason for this error is as we are trying to access a local variable pi and radius in a global scope whereas the local variable only works inside circle() or local scope. There is a way to solve it by declaring pi and radius as global or declaring them outside the function. Where any function can access them.
In Python or any other programming languages, we often use the nonlocal variable inside nested functions. Now, what do I mean by nested functions?
In general, a nested function is a set of functions declared inside another function. Given below is an example of a nested function.
def circle():    pi = 3.142   # I could have also used "math" library (math.pi)    radius = 5   # Interger value for radius    area_of_circle = pi * (radius) ** 2    def circumference():        # Formula for circumference        circumference_of_circle = 2 * pi * radius            return circumference_of_circle    print(circumference())    # Calling the circumference function    return area_of_circleprint(circle())     # Calling the circle function
On executing this piece of code you will get the following as the output
31.419999999999998 78.55 
Let us now try to update the radius by 2 (multiply by 2) inside the circumference(). The reason that I’m specifically insisting to do this because as soon as you write radius = radius * 2 and run the code you will be prompted by UnboundLocalError seeing this you will change it to a global variable by saying global radius but this time you will get a new error as NameError. And now you will be baffled, don’t know what to do. There is a simple way to solve this “Go read the definition of a nonlocal variable”. Whenever there is a nested function you need to use a nonlocal variable. That’s it problem solved. Below is the way to create a nonlocal variable and access it.
def circle():    pi = 3.142   # I could have also used "math" library (math.pi)    radius = 5   # Interger value for radius    area_of_circle = pi * (radius) ** 2    def circumference():        nonlocal radius         # Nonlocal variable        radius = radius * 2        # Formula for circumference        circumference_of_circle = 2 * pi * radius            return circumference_of_circle    print(circumference())    # Calling the circumference function    return area_of_circleprint(circle())     # Calling the circle function
On executing this code you will get the output as
62.839999999999996 78.55 
This is the end of the article titled “Global, Local and Nonlocal variables in Python”. I hope you guys learned a thing or two by reading this article. Through this article, you learned how to get rid of two important Python errors such as NameError and UnboundLocalError which were troubling you all these days or years or whatever. Now you can easily debug these two errors with a smile on your face without losing a sweat. If you have any comments or suggestions about this article, then the comment section is all yours. Stay tuned for more updates, until then goodbye. Stay safe and happy coding and see you next time.