Python Tutorial (31) - Namespaces and Scopes

Time: Column:Python views:213

Namespaces in Python

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

Namespaces provide a way to avoid naming conflicts in a project. Each namespace is independent, meaning no name within a namespace can be duplicated, but names in different namespaces can be identical without causing conflicts.

Let’s use a computer system example: a folder can contain multiple subfolders, and each subfolder cannot have files with the same name. However, files in different folders can have the same name.

Python Tutorial (31) - Namespaces and Scopes

Types of Namespaces

There are generally three types of namespaces:

  1. Built-in Names: These are names built into Python, such as function names (abs, char) and exception names (BaseException, Exception).

  2. Global Names: Names defined at the module level, including functions, classes, and variables.

  3. Local Names: Names defined within functions, including parameters and locally defined variables.

Python Tutorial (31) - Namespaces and Scopes

Namespace Lookup Order

When Python looks for a variable (e.g., runoob), it searches in the following order:

  • Local namespace → Global namespace → Built-in namespace.

If the variable is not found, Python will raise a NameError:

NameError: name 'runoob' is not defined

Namespace Lifetime

The lifetime of a namespace is determined by the scope of its objects. Once the object is done executing, the namespace is no longer accessible.

Example:

# var1 is a global name
var1 = 5

def some_func():
    # var2 is a local name
    var2 = 6

    def some_inner_func():
        # var3 is a nested local name
        var3 = 7

Python Tutorial (31) - Namespaces and Scopes

Scope in Python

A scope is a textual region of a Python program where a namespace is directly accessible. This means an unqualified reference to a name will try to find the name in the current namespace.

In Python, variables are not accessible everywhere in the code. The location where a variable is assigned determines its scope. There are four types of scopes in Python:

  • L (Local): Innermost scope, containing local variables (e.g., inside a function).

  • E (Enclosing): The scope of any enclosing function, excluding global scope.

  • G (Global): The outermost scope, usually the module-level scope.

  • B (Built-in): Contains built-in functions and keywords.

Scope lookup order: Local → Enclosing → Global → Built-in.

g_count = 0  # Global scope

def outer():
    o_count = 1  # Enclosing scope
    
    def inner():
        i_count = 2  # Local scope

Global and Nonlocal Keywords

When modifying variables from an outer scope within a function, the global or nonlocal keyword must be used.

Example: Using global

num = 1

def fun1():
    global num
    print(num)  # Outputs: 1
    num = 123
    print(num)  # Outputs: 123

fun1()
print(num)  # Outputs: 123

Example: Using nonlocal

def outer():
    num = 10
    
    def inner():
        nonlocal num
        num = 100
        print(num)  # Outputs: 100

    inner()
    print(num)  # Outputs: 100

outer()

Example of a Scope Error

a = 10

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

test()

This results in an error:

UnboundLocalError: local variable 'a' referenced before assignment

Variable Scope Modification Example:

Using global:

a = 10

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

test()  # Outputs: 11

Passing through function parameters:

a = 10

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

test(a)  # Outputs: 11