In this post, we will look at local variables as defined within a function, and global variables and how they can be referenced within a function and finally we will consider non-local variables. Summarily, we will discuss the scope and lifetime of variables in Python.
Local Variables
In practice developers usually try to limit the number of global variables in their programs as global variables can be accessed anywhere and can be modified anywhere and this can result in unexpected behaviors.
However, not all variables are global. When we define a function, we can create variables which are scoped only to that function and are not accessible or visible outside of the function to the compiler. These variables are referred to as local variables (as they are local to the function).
This is a great help in modular programming which has been proven to be easier to maintain, develop and test.
Scope and Lifetime of Local Variables
In the following function local variable called local_variable
has been created and initialized to hold the value 50.
def my_function(): local_variable = 50 print (local_variable) my_function()
Thus, when we ran the my_function()
it successfully printed out the value 50
which was held by the local_variable.
However, if we attempt to access local_variable outside the function, then it will generate an error. For example,
def my_function(): local_variable = 50 print (local_variable) my_function() print(local_variable)
When we run this code, we get the number 50 printed out from my_function(). However, an error is the reported by Python.
50
Traceback (most recent call last):
File "localvars.py", line 6, in <module>
print(local_variable)
NameError: name 'local_variable' is not defined
This indicates that local_variable
is undefined at the top level (which is the global scope). Thus, we can say that local_variable
is not globally defined. This is because local_variable
only exists and only has meaning inside my_function()
; outside of that function it is not visible.
In fact, each time the function is called, local_variable
comes back into existence as a new variable, so the value in local_variable
is not seen from one invocation of the function to another. This raises the question what happens if a global variable called local_variable
is defined? For example, if we have the following code snippet:
local_variable = 75 def my_function(): local_variable = 50 print (local_variable) my_function() print(local_variable)
Actually, this is fine and supported in Python. There are now two versions of local_variable
in the program; one of which is defined globally and one of which is defined within the context of the function. Python does not get confused between these and treats them as completely different variables.
Thus, if we run the above code we get
50
75
The value 50 does not overwrite the value 75 as they are completely different variables.
Global Variables
But what happens if we want to reference the global variable within a function. As long as Python does not think we have defined a local variable then all will be fine. For example,
var = 50 def my_function(): print (var) print (var)
The above code snippet will print the value 50. However, things go into error if we try to modify the global variable inside the function. At this point, Python thinks we are creating a local variable. If as part of the assignment we try to reference the current value of that local variable; we will get an error indicating that it currently does not have a value. For example,
var = 50 def my_function(): var = var + 1 print (var) my_function()
After running the above code snippet, we will get an error. Indicating that we have referenced var
before it was assigned a value; even though it was assigned a value globally before the function was called.
If we want to reference the global variable intentionally at this point we need to use the keyword global with the name of the variable. For example,
var = 50 def my_function(): global var var = var + 1 print (var) my_function() print (var)
Now, when we try to update the variable var
inside the function my_function()
, Python knows we mean the global version of the variable and uses that one. The result is that we now print out the value 51 and var
is updated to 51 for the variable var everywhere in the program.
Non-local Variables
It is possible to define functions inside other functions, and this can be very useful when we are working with collections of data and operations such as map()
(which maps a function to all the elements of a collection of data).
Scope and Lifetime of Non-local Variables
However, local variables are local to a specific function; even functions defined within another function cannot modify the outer function’s local variables. They can reference it, just as we could reference the global variable earlier; the issue is again modification.
The global keyword is no help here as the outer function’s variables are not global, they are local to a function. For example, if we define a nested function (inner) inside the parent outer function and want to modify the local field we will have a problem.
def outer(): title = "DroxElement" def inner(): title = "Space for Programming" print ("inner: ", title) inner() print ("outer: ", outer) outer()
In this example, both outer()
and inner()
functions modify the title variable. However, they are not the same title
variable and as long as this is what we need then that is fine; both functions have their own version of a title
local variable. This can be seen in the output where the outer function maintains its own value for title
.
inner : DroxElement
outer : Space for Programming
However, if we want for the inner()
function to modify the outer()
function’s title variable then we will have a problem. This problem can be solved using the nonlocal keyword. This indicates that a variable is not global but is also not local to the current function and Python should look within the scope in which the function is defined to fund a local variable with the same name.
If we now declare title
as nonlocal
in the inner()
function, then it will use the outer()
functions version of title
and thus when the inner()
function changes the title it will change it for both functions.
def outer(): title = "DroxElement" def inner(): nonlocal title title = "Space for Programming" print ("inner: ", title) inner() print ("outer: ", title) outer()
The output for the above code snippet is
inner: DroxElement
outer: Space for Programming
Also Read: Calculating Factorial Recursively in Python