LearnContact
Lesson 4520 min read

Namespaces

Learn what a namespace is, the different namespaces Python maintains, and how to inspect them with globals() and locals().

Introduction

Every name you use in Python — a variable, a function, a class — has to live somewhere Python can look it up. That "somewhere" is called a namespace. You already learned, in the Variable Scope lesson, which namespace gets searched first when a name is looked up. This lesson focuses on something more fundamental: what a namespace actually is.

Once you see a namespace for what it really is — just a mapping of names to objects, conceptually a dictionary — a lot of Python's behavior becomes far less mysterious.

What You Will Learn
  • What a namespace is, conceptually.
  • The different kinds of namespaces Python maintains (built-in, global, local, class).
  • How namespaces relate to, but are distinct from, scope.
  • How to inspect the contents of a namespace using globals() and locals().
  • Why each module gets its own separate namespace.

What is a Namespace?

A namespace is a mapping from names (as strings) to objects. Conceptually, it works exactly like a dictionary: each key is a name you have used in your code, like x or greet, and each value is the actual object that name currently refers to.

A namespace behaves like a dictionary
x = 10
name = "Alex"


def greet():
    pass


print(globals()["x"])
print(globals()["name"])
print(globals()["greet"])
Output
10
Alex
<function greet at 0x000001A2B3C4D5E0>

This is not just a helpful analogy — globals() literally returns a real dictionary object representing the current global namespace. When you write x = 10, Python is effectively adding the entry "x": 10 into that dictionary.

Simple Definition
  • A namespace is a collection of currently defined names.
  • Each name in a namespace points to exactly one object.
  • The same name can exist in multiple different namespaces at the same time, without conflict.

Kinds of Namespaces

Python maintains several separate namespaces at once, each created at a different time and lasting for a different duration. The same name, like "x", can exist independently in more than one of these at the same time.

Built-in Namespace

Contains names Python provides automatically, like print, len, and range. Created when the interpreter starts and lasts the entire program.

Global (Module) Namespace

Contains names defined at the top level of a single module (.py file). Created when the module is loaded and lasts until the program ends.

Local (Function) Namespace

Contains names defined inside a function, including its parameters. Created when the function is called and destroyed when it returns.

Class Namespace

Contains the names defined inside a class body — its methods and class-level attributes.

Four namespaces, same program
# built-in namespace already has: print, len, range, ...

count = 100  # lives in the global (module) namespace


class Robot:
    version = "v1"  # lives in the Robot class namespace


def process():
    count = 5  # a SEPARATE local namespace entry, unrelated to the global one
    print(count)


process()
print(count)
print(Robot.version)
Output
5
100
v1

Notice that the local count inside process() and the global count are two entirely separate entries living in two entirely separate namespaces — changing one never touches the other.

Namespaces vs Scope

It is easy to blend these two ideas together, so it is worth being precise. A namespace is the mapping itself — the actual collection of name-to-object entries. Scope is the set of rules Python uses to decide which namespace to search first, second, and so on, when it looks up a name (this is the LEGB rule you covered in the Variable Scope lesson).

Namespace

  • The actual storage — a mapping of names to objects.
  • Answers: "What names exist, and what do they point to?"
  • Examples: the global namespace, a function's local namespace.

Scope

  • The lookup rule — which namespace(s) get searched, and in what order.
  • Answers: "Where should Python look for this name?"
  • Example: the LEGB order — Local, Enclosing, Global, Built-in.
One-Line Distinction

A namespace is where names live; scope is the rule for which namespace gets checked first when a name is used.

Inspecting Namespaces with globals() and locals()

Python gives you two built-in functions that return a namespace as an actual dictionary you can inspect: globals() for the module namespace, and locals() for whatever the current local namespace is.

Using globals()
language = "Python"
version = 3

names = globals()
print(type(names))
print("language" in names)
print(names["version"])
Output
<class 'dict'>
True
3
Using locals() inside a function
def describe(item, price):
    tax = price * 0.1
    print(locals())


describe("Book", 20)
Output
{'item': 'Book', 'price': 20, 'tax': 2.0}

Inside describe(), locals() shows exactly the local namespace at that moment: the two parameters and the tax variable created so far, all as one plain dictionary.

locals() Is Read-Only in Functions

Modifying the dictionary returned by locals() inside a function is not guaranteed to actually change the function's real local variables — treat it as a snapshot for inspection, not a way to edit local names.

Module Namespaces

Every .py file you write gets its own private global namespace. This is why two completely different files can each define a variable called total or a function called process without ever colliding with each other.

math_utils.py
# math_utils.py
def process(x):
    return x * 2
text_utils.py
# text_utils.py
def process(text):
    return text.upper()
main.py
import math_utils
import text_utils

print(math_utils.process(5))
print(text_utils.process("hello"))
Output
HELLO
10

Both files define a function named process, but because each module has its own separate namespace, math_utils.process and text_utils.process are completely distinct entries. You reach into each module's namespace using dot notation, exactly like reaching into a dictionary by key.

Common Mistakes

Avoid These Mistakes
  • Confusing "namespace" (the mapping of names) with "scope" (the rule for searching namespaces) — they are related but not the same thing.
  • Assuming locals() lets you freely create or modify local variables inside a function — this is unreliable and should be avoided.
  • Forgetting that each module has its own namespace, then being surprised that from module import * can silently overwrite existing global names.
  • Thinking there is only one namespace in a program — there are always at least the built-in and global namespaces, plus a new local one for every function call.

Best Practices

  • Use globals() and locals() mainly for debugging and learning, not as a regular part of program logic.
  • Prefer accessing another module's names through its own namespace (module.name) rather than importing everything with *.
  • Keep the global namespace of a module clean — avoid dumping many unrelated top-level variables into one file.
  • Remember that a class also has its own namespace, which is why attribute lookups on an instance can fall back to the class.
  • When debugging "name not found" errors, check which namespace you expected the name to live in.

Frequently Asked Questions

Is a namespace literally a Python dictionary?

For the global and local namespaces, yes — globals() and locals() return actual dict objects. Some namespaces (like class namespaces accessed via __dict__) work the same way conceptually, even if the internal implementation detail can differ slightly.

How is this different from the Variable Scope lesson?

The Variable Scope lesson covered the LEGB rule — the order Python searches through namespaces when resolving a name. This lesson covers what those namespaces actually are and what they contain.

Why can two functions both have a variable named total without conflict?

Because each function call creates its own brand-new local namespace. The two total entries live in two completely separate mappings and never interact.

Do built-in names like print live in the global namespace of my file?

No, they live in a separate built-in namespace. Your file's global namespace only contains what you actually define at the top level; print is found through the built-in namespace as a fallback.

Can I have a variable with the same name as a built-in function?

Yes, for example writing list = [1, 2, 3] adds "list" to your global namespace, which then shadows the built-in list. This is technically legal but discouraged, since it hides the original built-in for the rest of that scope.

Key Takeaways

  • A namespace is a mapping from names to objects — conceptually, and often literally, a dictionary.
  • Python maintains several namespaces at once: built-in, global (module), local (function), and class.
  • Namespace is what stores the names; scope is the rule for which namespaces get searched, and in what order.
  • globals() and locals() let you inspect the current global and local namespaces as real dictionaries.
  • Every module has its own independent global namespace, which prevents naming collisions between different files.

Summary

A namespace is simply where names live — a mapping of names to the objects they refer to, whether that is the built-in namespace, a module's global namespace, a function's local namespace, or a class's namespace. Keeping these separate is what allows the same name to be reused safely across different files and functions.

In this lesson, you learned what a namespace is, the different kinds Python maintains, how namespaces differ from scope, and how to inspect them directly with globals() and locals(). Next, you will learn comprehensions — a compact, readable way to build lists, sets, and dictionaries.

Lesson 45 Completed
  • You understand what a namespace is and how it maps names to objects.
  • You can identify the built-in, global, local, and class namespaces.
  • You can inspect namespaces using globals() and locals().
  • You are ready to learn about comprehensions.
Next Lesson →

List, Set & Dictionary Comprehensions