Local Namespace and Variables#

Variable names are stored in a namespace, and must be unique within a namespace. Variables that are defined in the main body of a script are stored in the global namespace and are referred to as global variables.

The global namespace is accessible both in the script body and inside of functions:

x = 5

def get_x():
    return x
get_x()
5

however, when variables are defined inside of the function (including arguments) these are only accessible within that function. For example:

def make_var():
    func_var = 4
    return func_var
make_var()
4
func_var
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 1
----> 1 func_var

NameError: name 'func_var' is not defined

This is because a function has it’s own namespace, referred to as a local namespace. Variables in the global namespace are still accessible inside the local namespace, but variables defined in the local namespace are not available in the global namespace (or any other namespaces that encompasses it).

If a variable is defined in a local namespace with the same name as a variable in the global namespace, then the local variable will be used by default.

For example, if we were to define func_var as a global variable, make_var will instance a local variable instead of reassigning a new value to the global variable:

func_var = 6

print('Before function', func_var)
print('Function return', make_var())
print('After function', func_var)
Before function 6
Function return 4
After function 6

In other words Python will check the local namespace before the global namespace.

As stated above, function arguments can also be treated as local variables.

def arg_var(x):
    return x
x = 5

arg_var(2)
2

Warning

Although variable names are restricted to namespaces, the objects that they represent are not. This is not so important to keep in mind with numbers and strings (which are passed in by value), but it is important for objects that can be altered, such as arrays and dictionaries.

For example, if we were to pass a dictionary into a function, any alterations made to that dictionary inside the function would remain outside (as there is only one dictionary object being used).

def add_to_dict(d):
    d['key'] = 'value'
    return d
d = {}

print('Dictionary before the function call:', d)
print('Function return:', add_to_dict(d))
print('Dictionary after the function call:', d)
Dictionary before the function call: {}
Function return: {'key': 'value'}
Dictionary after the function call: {'key': 'value'}