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 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.
x = 10
name = "Alex"
def greet():
pass
print(globals()["x"])
print(globals()["name"])
print(globals()["greet"])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.
- 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.
# 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)5
100
v1Notice 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.
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.
language = "Python"
version = 3
names = globals()
print(type(names))
print("language" in names)
print(names["version"])<class 'dict'>
True
3def describe(item, price):
tax = price * 0.1
print(locals())
describe("Book", 20){'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.
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
def process(x):
return x * 2# text_utils.py
def process(text):
return text.upper()import math_utils
import text_utils
print(math_utils.process(5))
print(text_utils.process("hello"))HELLO
10Both 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
- 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.
- 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.