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.
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
The value 50 does not overwrite the value 75 as they are completely different 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.
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
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
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
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