Allow me to quote the documentation:
A namespace is a mapping from names to objects. Most namespaces are currently implemented as Python dictionaries, but that’s normally not noticeable in any way (except for performance), and it may change in the future. Examples of namespaces are: the set of built-in names (containing functions such as abs()
, and built-in exception names); the global names in a module; and the local names in a function invocation. In a sense the set of attributes of an object also form a namespace. The important thing to know about namespaces is that there is absolutely no relation between names in different namespaces;
So, as @user2357112 supports Monica said in the comments:
There's more than one way a namespace can be conceptually associated with an object.
Kent Johnson also talked about it well:
Another way to think of it is, a namespace is a place where names are
looked up. When you use a bare name (not an attribute), it is looked up
in the local namespace, then the global namespace, then the built-in
namespace. For example:
y = 2 # Defines y in the global (module) namespace
def f():
x = 1 # Defines x in the local (function) namespace
# This looks up x, finds it in the local namespace
# looks up abs, finds it in the built-in namespace
print abs(x)
# This looks up y, finds it in the global namespace
print y
Note that none of the above namespaces have a related __dict__
attribute, the namespace mappings are not stored that way.
Objects also define a sort of namespace, where attributes are defined
and looked up. The dict containing the namespace of an object is itself
stored as an attribute of the object, called __dict__
. So __dict__
is an
implementation detail of the way object attributes are stored.
As a beginner, it is important to understand the way bare names are
looked up (local
, global
, built-in
namespace) and a bit about the way
attributes work. You don't have to be concerned with the implementation
details such as __dict__
.
You can explore different namespaces using the dir()
function, which:
Without arguments, return the list of names in the current local scope. With an argument, attempt to return a list of valid attributes for that object.
def foo(a):
if a == 3:
b = 1
else:
c = 1
print("Local function namespace: ", dir())
a = 2
b = 3
foo.custom_attr = "some attr"
foo(a)
foo(b)
print("Global namespace: ", dir())
print("foo object namespace via dir: ", dir(foo))
print("foo object namespace via __dict__: ", foo.__dict__)
print("Built-in namespace: ", dir(__builtins__))
Output:
Local function namespace: ['a', 'c']
Local function namespace: ['a', 'b']
Global namespace: ['__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'a', 'b', 'foo']
foo object namespace via dir: ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'custom_attr']
foo object namespace via __dict__: {'custom_attr': 'some attr'}
Built-in namespace: ['ArithmeticError', 'AssertionError', 'AttributeError', [...]