Skip to content

Python Namespaces and Scopes

Understanding namespaces and scopes is key to mastering how Python organizes and looks up variables. This concept is crucial for avoiding naming conflicts and writing clear, maintainable code.

What is a Namespace?

A namespace is a mapping from names to objects. Simply put, it's like a dictionary where keys are variable names and values are corresponding objects. Everything in Python—variables, functions, classes, modules—exists in some namespace.

Python mainly has the following types of namespaces:

  1. Built-in Namespace: Contains all Python built-in functions and exceptions, such as print(), len(), ValueError. This namespace is created when the Python interpreter starts and exists throughout the entire program execution.

  2. Global Namespace: Belongs to a single module (a .py file). When a module is imported, its global namespace is created. It contains all global variables and functions defined in that module.

  3. Local Namespace: When a function is called, a local namespace is created for that function. It contains all variables and parameters defined within the function. When the function returns, this namespace is deleted.

What is a Scope?

A scope is a textual region in a program where a certain namespace can be directly accessed. In other words, it defines which parts of your code can use a variable name without any prefix.

Python's scope rules are commonly referred to as the LEGB Rule. The Python interpreter looks up a variable in this order:

  1. L (Local): Local scope, i.e., inside the current function. This is the first stop.
  2. E (Enclosing): Scope of the enclosing function outside the closure. If a function is nested within another function, the interpreter will look in the outer function's local scope.
  3. G (Global): Global scope, i.e., the top level of the current module. This is the second-to-last stop.
  4. B (Built-in): Built-in scope, containing Python's built-in functions and exceptions. This is the last stop. If not found here either, Python raises a NameError.

Scope Example

python
x = 'global x' # Global scope (G)

def outer_func():
    y = 'enclosing y' # Enclosing scope (E) for inner_func

    def inner_func():
        z = 'local z' # Local scope (L)
        print(z) # Lookup order: L -> E -> G -> B. Found z in L
        print(y) # Lookup order: L -> E -> G -> B. Found y in E
        print(x) # Lookup order: L -> E -> G -> B. Found x in G
        print(len("hello")) # Lookup order: L -> E -> G -> B. Found len in B

    inner_func()

outer_func()

global and nonlocal Keywords

By default, you can only read global variables or enclosing variables within a function. If you want to modify them inside a function, you need to use the global or nonlocal keyword to explicitly declare it.

global Keyword

Used to modify variables in global scope within a function.

python
count = 0 # Global variable

def increment():
    global count # Declare that count is a global variable
    count += 1

increment()
print(count) # Output: 1

nonlocal Keyword

Used to modify variables from the outer (but non-global) function within a nested function.

python
def outer():
    level = 'outer level' # Enclosing variable

    def inner():
        nonlocal level # Declare that level is from the outer function
        level = 'inner level'
        print(f"Inside inner: {level}")

    inner()
    print(f"Inside outer: {level}")

outer()
# Output:
# Inside inner: inner level
# Inside outer: inner level

Understanding the LEGB rule and usage of global/nonlocal helps you better organize code and avoid unexpected variable shadowing and UnboundLocalError errors.

Content is for learning and research only.