Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Navigating Namespaces and Scope in Python
This tutorial covers Python namespaces, the structures used to organize the symbolic names assigned to objects in a Python program.
The previous tutorials in this series have emphasized the importance of objects in Python. Objects are everywhere! Virtually everything that your Python program creates or acts on is an object.
An assignment statement creates a symbolic name that you can use to reference an object. The statement x = 'foo' creates a symbolic name x that refers to the string object 'foo'.
In a program of any complexity, you’ll create hundreds or thousands of such names, each pointing to a specific object. How does Python keep track of all these names so that they don’t interfere with one another?
In this tutorial, you’ll learn:
- How Python organizes symbolic names and objects in namespaces
- When Python creates a new namespace
- How namespaces are implemented
- How variable scope determines symbolic name visibility
Free Bonus: 5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.
Namespaces in Python
A namespace is a collection of currently defined symbolic names along with information about the object that each name references. You can think of a namespace as a dictionary in which the keys are the object names and the values are the objects themselves. Each key-value pair maps a name to its corresponding object.
Namespaces are one honking great idea—let’s do more of those!
— The Zen of Python, by Tim Peters
As Tim Peters suggests, namespaces aren’t just great. They’re honking great, and Python uses them extensively. In a Python program, there are four types of namespaces:
- Built-In
- Global
- Enclosing
- Local
These have differing lifetimes. As Python executes a program, it creates namespaces as necessary and deletes them when they’re no longer needed. Typically, many namespaces will exist at any given time.
The Built-In Namespace
The built-in namespace contains the names of all of Python’s built-in objects. These are available at all times when Python is running. You can list the objects in the built-in namespace with the following command:
>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError',
'BaseException','BlockingIOError', 'BrokenPipeError', 'BufferError',
'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError',
'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError',
'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError',
'Exception', 'False', 'FileExistsError', 'FileNotFoundError',
'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError',
'ImportError', 'ImportWarning', 'IndentationError', 'IndexError',
'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt',
'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None',
'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError',
'OverflowError', 'PendingDeprecationWarning', 'PermissionError',
'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning',
'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration',
'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError',
'TimeoutError', 'True', 'TypeError', 'UnboundLocalError',
'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError',
'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError',
'Warning', 'ZeroDivisionError', '_', '__build_class__', '__debug__',
'__doc__', '__import__', '__loader__', '__name__', '__package__',
'__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray',
'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex',
'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate',
'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset',
'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input',
'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list',
'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct',
'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr',
'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod',
'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
You’ll see some objects here that you may recognize from previous tutorials—for example, the StopIteration exception, built-in functions like max() and len(), and object types like int and str.
The Python interpreter creates the built-in namespace when it starts up. This namespace remains in existence until the interpreter terminates.
The Global Namespace
The global namespace contains any names defined at the level of the main program. Python creates the global namespace when the main program body starts, and it remains in existence until the interpreter terminates.
Strictly speaking, this may not be the only global namespace that exists. The interpreter also creates a global namespace for any module that your program loads with the import statement. For further reading on main functions and modules in Python, see these resources:
- Defining Main Functions in Python
- Python Modules and Packages—An Introduction
- Course: Python Modules and Packages
You’ll explore modules in more detail in a future tutorial in this series. For the moment, when you see the term global namespace, think of the one belonging to the main program.
The Local and Enclosing Namespaces
As you learned in the previous tutorial on functions, the interpreter creates a new namespace whenever a function executes. That namespace is local to the function and remains in existence until the function terminates.
Functions don’t exist independently from one another only at the level of the main program. You can also define one function inside another:
1>>> def f():
2... print('Start f()')
3...
4... def g():
5... print('Start g()')
6... print('End g()')
7... return
8...
9... g()
10...
11... print('End f()')
12... return
13...
14
15>>> f()
16Start f()
17Start g()
18End g()
19End f()
In this example, function g() is defined within the body of f(). Here’s what’s happening in this code:
- Lines 1 to 12 define
f(), the enclosing function. - Lines 4 to 7 define
g(), the enclosed function. - On line 15, the main program calls
f(). - On line 9,
f()callsg().
When the main program calls f(), Python creates a new namespace for f(). Similarly, when f() calls g(), g() gets its own separate namespace. The namespace created for g() is the local namespace, and the namespace created for f() is the enclosing namespace.
Each of these namespaces remains in existence until its respective function terminates. Python might not immediately reclaim the memory allocated for those namespaces when their functions terminate, but all references to the objects they contain cease to be valid.
Variable Scope
The existence of multiple, distinct namespaces means several different instances of a particular name can exist simultaneously while a Python program runs. As long as each instance is in a different namespace, they’re all maintained separately and won’t interfere with one another.
But that raises a question: Suppose you refer to the name x in your code, and x exists in several namespaces. How does Python know which one you mean?
The answer lies in the concept of scope. The scope of a name is the region of a program in which that name has meaning. The interpreter determines this at runtime based on where the name definition occurs and where in the code the name is referenced.
Further Reading: See the Wikipedia page on scope in computer programming for a very thorough discussion of variable scope in programming languages.
If you’d prefer to dive into a video course, then check out Exploring Scopes and Closures in Python or get back to the fundamentals with Python Basics: Scopes.
To return to the above question, if your code refers to the name x, then Python searches for x in the following namespaces in the order shown:
- Local: If you refer to
xinside a function, then the interpreter first searches for it in the innermost scope that’s local to that function. - Enclosing: If
xisn’t in the local scope but appears in a function that resides inside another function, then the interpreter searches in the enclosing function’s scope. - Global: If neither of the above searches is fruitful, then the interpreter looks in the global scope next.
- Built-in: If it can’t find
xanywhere else, then the interpreter tries the built-in scope.
This is the LEGB rule as it’s commonly called in Python literature (although the term doesn’t actually appear in the Python documentation). The interpreter searches for a name from the inside out, looking in the local, enclosing, global, and finally the built-in scope:

If the interpreter doesn’t find the name in any of these locations, then Python raises a NameError exception.
Examples
Several examples of the LEGB rule appear below. In each case, the innermost enclosed function g() attempts to display the value of a variable named x to the console. Notice how each example prints a different value for x depending on its scope.
Example 1: Single Definition
In the first example, x is defined in only one location. It’s outside both f() and g(), so it resides in the global scope:
1>>> x = 'global'
2
3>>> def f():
4...
5... def g():
6... print(x)
7...
8... g()
9...
10
11>>> f()
12global
The print() statement on line 6 can refer to only one possible x. It displays the x object defined in the global namespace, which is the string 'global'.
Example 2: Double Definition
In the next example, the definition of x appears in two places, one outside f() and one inside f() but outside g():
1>>> x = 'global'
2
3>>> def f():
4... x = 'enclosing'
5...
6... def g():
7... print(x)
8...
9... g()
10...
11
12>>> f()
13enclosing
As in the previous example, g() refers to x. But this time, it has two definitions to choose from:
- Line 1 defines
xin the global scope. - Line 4 defines
xagain in the enclosing scope.
According to the LEGB rule, the interpreter finds the value from the enclosing scope before looking in the global scope. So the print() statement on line 7 displays 'enclosing' instead of 'global'.
Example 3: Triple Definition
Next is a situation in which x is defined here, there, and everywhere. One definition is outside f(), another one is inside f() but outside g(), and a third is inside g():
1>>> x = 'global'
2
3>>> def f():
4... x = 'enclosing'
5...
6... def g():
7... x = 'local'
8... print(x)
9...
10... g()
11...
12
13>>> f()
14local
Now the print() statement on line 8 has to distinguish between three different possibilities:
- Line 1 defines
xin the global scope. - Line 4 defines
xagain in the enclosing scope. - Line 7 defines
xa third time in the scope that’s local tog().
Here, the LEGB rule dictates that g() sees its own locally defined value of x first. So the print() statement displays 'local'.
Example 4: No Definition
Last, we have a case in which g() tries to print the value of x, but x isn’t defined anywhere. That won’t work at all: