Python Global Keyword Explained: Reassigning Variables

In Python, the global keyword tells the interpreter that a variable defined inside a function belongs to the module-level namespace rather than the local scope. This article explains the exact mechanics of the global keyword, why it is mandatory when reassigning a variable inside a function, how Python's name-resolution rules operate, and the crucial distinction between variable reassignment and in-place mutation.

The Scope Problem: Local vs. Global

By default, Python treats any variable assigned inside a function as a local variable. When a function only reads a variable, Python checks the local scope first; if the variable is not found, it traverses upward to the enclosing and global scopes.

However, the moment an assignment statement (such as =) targets a variable name inside a function, Python marks that name as local for the entire function body.

Consider this example without global:

counter = 0

def increment():
    counter = counter + 1  # Raises UnboundLocalError

Because counter is assigned a value inside increment(), Python flags counter as local. When the expression evaluates counter + 1, it tries to read the local variable before it has been assigned, resulting in an UnboundLocalError: local variable 'counter' referenced before assignment.

The Exact Purpose of the global Keyword

The global keyword explicitly overrides this default scoping behavior. It informs Python that a specific identifier refers to the variable defined in the top-level (module) scope, preventing the creation of a local variable with the same name.

counter = 0

def increment():
    global counter
    counter = counter + 1

increment()
print(counter)  # Output: 1

By declaring global counter, the assignment statement counter = counter + 1 redirects the binding operation to the module-level counter rather than creating a shadow variable in the local namespace.

Reassignment vs. Mutation

A common source of confusion is the difference between reassigning a variable and mutating an object in place.

shared_list = []

def modify_list():
    # No global keyword needed: modifying the object, not reassigning the name
    shared_list.append(1)

def replace_list():
    global shared_list
    # global keyword REQUIRED: rebinding the name to a new list object
    shared_list = [2, 3]

Summary

The sole purpose of the global keyword during reassignment is to bind an assignment target to the module-level namespace. Without it, any assignment inside a function automatically creates a local variable, either shadowing the outer variable or causing an UnboundLocalError if referenced prior to initialization.