Python Namespaces & Variable Scope: The LEGB Resolution Rule

As programs grow larger, reusing common variable names like total, i, or data becomes inevitable. How does Python ensure that a variable inside one function does not accidentally overwrite an identical variable in another module? The answer lies in Namespaces and Variable Scopes.

Python LEGB Scope Resolution Hierarchy Diagram

Figure 29.1: Concentric hierarchy of Python's LEGB variable resolution: Local -> Enclosing -> Global -> Built-in.


The LEGB Rule for Name Resolution

Whenever Python encounters a variable name, it searches through four nested scopes in strict order:

• 1. Local (L): Names assigned within the current active function or lambda.

• 2. Enclosing (E): Names defined in any outer enclosing functions (closures).

• 3. Global (G): Names assigned at the top level of the current .py file/module.

• 4. Built-in (B): Preloaded names provided by Python (print, len, range, ZeroDivisionError).


1. The global Keyword

By default, assigning to a variable inside a function creates a new local variable. To modify a top-level global variable from within a function, you must declare it with global:

counter = 0  # Global variable

def increment():
    global counter  # Tell Python to use the global variable
    counter += 1

increment()
increment()
print("Final Counter:", counter)  # 2

2. The nonlocal Keyword (Nested Functions & Closures)

The nonlocal keyword allows an inner function to modify a variable in the outer enclosing function's scope without polluting the global namespace:

def create_counter():
    count = 0  # Enclosing scope

    def step():
        nonlocal count  # Refers to count in create_counter
        count += 1
        return count

    return step

my_counter = create_counter()
print(my_counter())  # 1
print(my_counter())  # 2
print(my_counter())  # 3

Frequently Asked Questions (FAQ)

How can you inspect local and global namespaces at runtime?

You can call the built-in functions locals() and globals(). Both return standard Python dictionaries containing all currently active variable names and their object bindings.
Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Stumbleupon Share on Tumblr Share on Reddit Share on Diggit

You may also like this!