Namespace and Scope in Python: Understand Where Names Live

Introduction

In this chapter, you will learn namespace and scope in Python, two concepts that explain how variable names are stored and resolved. Understanding this helps you avoid many confusing bugs, especially in functions and nested functions. Once you master scope rules, your code becomes safer, cleaner, and easier to debug.

Prerequisites

  • Python 3.10+ installed
  • Basic understanding of variables, functions, and classes
  • Ability to run .py files in terminal or IDE

What Is a Namespace

A namespace is a mapping between names and objects.

Examples of namespaces:

  • built-in namespace (len, print, str, ...)
  • global namespace (module-level names)
  • local namespace (inside functions)

You can think of namespace as a "name dictionary" Python uses to find values.

What Is Scope

Scope is the region where a name can be accessed directly.

Main scope levels in Python:

  • local scope
  • enclosing scope
  • global scope
  • built-in scope

This lookup order is often called LEGB:

  • Local
  • Enclosing
  • Global
  • Built-in

1) Local and Global Scope

python
# Global variable
course = "Python Basics"
 
 
def show_info():
    # Local variable
    lesson = "Namespace and Scope"
    print(course)  # accessible
    print(lesson)  # accessible
 
 
show_info()
 
# print(lesson)  # NameError: lesson is local only

lesson exists only inside show_info().

2) Global Keyword

Use global when you need to modify a global variable inside a function.

python
# Global counter
count = 0
 
 
def increase():
    global count
    count += 1
 
 
increase()
increase()
print(count)  # 2

Without global, assignment creates a new local variable instead.

3) Enclosing Scope and nonlocal

nonlocal is used in nested functions to modify variables in enclosing (outer function) scope.

python
def outer():
    value = 10
 
    def inner():
        nonlocal value
        value += 5
        print("Inner value:", value)
 
    inner()
    print("Outer value:", value)
 
 
outer()

This updates value in outer() scope, not global scope.

Tip

When to Use nonlocal

Use nonlocal in closures when inner functions must update outer function state.

4) Built-in Namespace

Built-in names are always available unless shadowed.

python
print(len([1, 2, 3]))  # built-in len

Avoid reusing built-in names:

python
# Bad practice: shadowing built-in name
len = 100
# print(len([1, 2]))  # This will fail because len is no longer function here

5) LEGB Lookup Demo

This example shows how Python resolves a name.

python
x = "global_x"
 
 
def outer():
    x = "enclosing_x"
 
    def inner():
        x = "local_x"
        print(x)  # local_x
 
    inner()
    print(x)  # enclosing_x
 
 
outer()
print(x)  # global_x

Python picks the nearest available scope first.

6) Real Mini Example: Score Tracker with Closure

This example uses enclosing scope and nonlocal to maintain state.

python
def make_score_tracker():
    # Enclosing scope variable
    total = 0
    count = 0
 
    def add_score(score):
        nonlocal total, count
        total += score
        count += 1
        avg = total / count
        print(f"Added: {score}, Current average: {avg:.2f}")
 
    return add_score
 
 
# Create tracker function
tracker = make_score_tracker()
 
# Update scores over time
tracker(90)
tracker(80)
tracker(95)

This is a practical closure pattern for lightweight state management.

Warning

Avoid overusing global variables in larger projects.
Too many globals make code harder to test and maintain.

Common Beginner Mistakes

Mistake 1: Expecting Local Variables Outside Functions

Local names are destroyed after function execution ends.

Mistake 2: Forgetting global or nonlocal for Assignment

Assignment in inner scopes creates local variables unless explicitly declared.

Mistake 3: Shadowing Built-ins

Using names like list, str, or len as variable names can break expected behavior.

Surprise Practice Challenge

Build a "Study Session Counter":

  1. Create function make_session_counter()
  2. Inside, keep sessions and total_minutes in enclosing scope
  3. Return inner function add_session(minutes)
  4. Use nonlocal to update state
  5. Print total sessions and average minutes after each update

If you finish this, you understand scope deeply enough to use closures confidently.

FAQ

What is the difference between namespace and scope?

Namespace is where names are stored; scope is where names are visible/accessed directly.

Should I avoid global completely?

Not completely, but use it carefully. Prefer passing values and returning results in most cases.

Is nonlocal the same as global?

No. nonlocal targets enclosing function scope, while global targets module-level scope.

Why is LEGB important?

It explains exactly where Python looks for names, which helps debug variable-related issues quickly.