Easy Tutorial
❮ Python String Join Python Os Write ❯

Python3 Namespaces and Scopes

Namespaces

Here is a passage from the official documentation:

A namespace is a mapping from names to objects. Most namespaces are currently implemented as Python dictionaries.

A namespace is a mapping from names to objects, and most namespaces are implemented using Python dictionaries.

Namespaces provide a way to avoid name conflicts in a project. Each namespace is independent and unrelated, so no duplicates are allowed within a single namespace, but different namespaces can have the same names without any issues.

We can use an example from a computer system: a folder (directory) can contain multiple subfolders, and each subfolder cannot have the same filename, but different subfolders can have files with the same name.

There are generally three types of namespaces:

Namespace lookup order:

Suppose we want to use the variable tutorialpro, then Python's lookup order is: Local namespace -> Global namespace -> Built-in namespace.

If the variable tutorialpro is not found, it will stop the search and raise a NameError exception:

NameError: name 'tutorialpro' is not defined.

The lifespan of a namespace depends on the scope of the object. If the object's execution is completed, the lifespan of the namespace ends.

Therefore, we cannot access objects from an inner namespace from an outer namespace.

Example

# var1 is a global name
var1 = 5
def some_func(): 
    # var2 is a local name
    var2 = 6
    def some_inner_func(): 
        # var3 is an enclosed local name
        var3 = 7

As shown in the diagram below, the same object name can exist in multiple namespaces.


Scopes

A scope is a textual region of a Python program where a namespace is directly accessible. "Directly accessible" here means that an unqualified reference to a name attempts to find the name in the namespace.

A scope is a textual region of a Python program where a namespace can be directly accessed.

In a Python program, directly accessing a variable will search from the innermost to the outermost scopes until it is found; otherwise, it will raise an undefined error.

In Python, variables are not accessible from every location; their accessibility depends on where they are assigned.

The scope of a variable determines which part of the program can access that specific variable name. There are four types of scopes in Python:

The order of rules is: L -> E -> G -> B.

If a variable is not found locally, it will be searched in the enclosing scope (e.g., a closure), then globally, and finally in the built-ins.

g_count = 0  # Global scope
def outer():
    o_count = 1  # Scope outside the closure function
    def inner():
        i_count = 2  # Local scope

The built-in scope is implemented through a standard module named builtins, but this variable name itself is not placed in the built-in scope, so it must be imported to use it. In Python 3.0, you can use the following code to see which predefined variables are available:

>>> import builtins
>>> dir(builtins)

In Python, only modules, classes, and functions introduce new scopes. Other code blocks (such as if/elif/else/, try/except, for/while, etc.) do not introduce new scopes. This means that variables defined within these blocks can be accessed externally, as shown in the following code:

>>> if True:
...  msg = 'I am from tutorialpro'
... 
>>> msg
'I am from tutorialpro'
>>>

In this example, the variable msg is defined within an if block, but it can still be accessed outside the block.

If msg is defined within a function, it becomes a local variable and cannot be accessed externally:

>>> def test():
...     msg_inner = 'I am from tutorialpro'
... 
>>> msg_inner
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'msg_inner' is not defined
>>>

The error message indicates that msg_inner is not defined and cannot be used because it is a local variable and can only be used within the function.

Global and Local Variables

Variables defined inside a function have a local scope, while variables defined outside a function have a global scope.

Local variables can only be accessed within the function they are declared, whereas global variables can be accessed throughout the entire program. When a function is called, all variable names declared within the function are added to the scope. Here is an example:

#!/usr/bin/python3

total = 0 # This is a global variable
# Function definition
def sum( arg1, arg2 ):
    # Return the sum of the two arguments
    total = arg1 + arg2 # total is a local variable here
    print ("Inside the function, total is a local variable: ", total)
    return total

# Calling the sum function
sum( 10, 20 )
print ("Outside the function, total is a global variable: ", total)

Output of the above example:

Inside the function, total is a local variable:  30
Outside the function, total is a global variable:  0

Global and Nonlocal Keywords

To modify variables in the outer scope from within an inner scope, you need to use the global and nonlocal keywords.

The following example modifies a global variable num:

#!/usr/bin/python3

num = 1
def fun1():
    global num  # Use the global keyword to declare
    print(num) 
    num = 123
    print(num)
fun1()
print(num)

Output of the above example:

1
123
123

To modify variables in the enclosing scope (non-global outer scope), you need to use the nonlocal keyword, as shown in the following example:

#!/usr/bin/python3

def outer():
    num = 10
    def inner():
        nonlocal num   # Use the nonlocal keyword to declare
        num = 100
        print(num)
    inner()
    print(num)
outer()

Output of the above example:

100
100

There is a special case where the following code is executed:

#!/usr/bin/python3

a = 10
def test():
    a = a + 1
    print(a)
test()

The above code will produce the following error:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    test()
  File "test.py", line 5, in test
    a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment

The error message indicates a local scope reference error because a in the test function is local, undefined, and cannot be modified.

To modify a as a global variable:

#!/usr/bin/python3

a = 10
def test():
    global a
    a = a + 1
    print(a)
test()

The output will be:

11

You can also pass the variable as a function parameter:

#!/usr/bin/python3

a = 10
def test(a):
    a = a + 1
    print(a)
test(a)

Execution output is:

11
❮ Python String Join Python Os Write ❯