History of the issue
Namespaces are one of the fundamental concepts of Python, present since the early implementations of the language. They are designed to organize names to avoid conflicts between variables, functions, and classes from different parts of a program.
The problem
In large projects, there are many functions, classes, variables, and modules. Without proper use of namespaces, it is possible to overwrite important names, encounter unexpected variable shadows, and face difficulties during testing and expanding.
The solution
In Python, a namespace is a mapping that links names to objects. There are different levels of namespaces: local, global, module, and class namespaces. Understanding this division ensures correct access to the needed objects and minimizes conflicts.
Code example:
def foo(): x = 10 # x in the local namespace of the function print(x) y = 20 # y in the global namespace of the module foo() print(y)
Key features:
What happens if a local variable is declared in the same function with the same name as a global one?
The local variable will "shadow" the global one during the execution of the function; outside of the function, the global variable remains unchanged.
a = 1 def test(): a = 2 print(a) # 2 test() print(a) # 1
How to get a list of all names in the current namespace?
The functions locals(), globals(), dir() return the corresponding mappings or lists of names in the current scope/namespace.
What is the difference between class and instance namespaces?
Class namespace defines attributes common to all instances of the class. Instance namespace — attributes of a specific object. Changes in the instance do not affect the class and vice versa.
Used from mymodule import * in all parts of a large project. As a result, function names got overwritten, leading to elusive bugs due to name conflicts between packages.
Pros:
Cons:
Switched to import aliases (import mymodule as mm), clear module structuring.
Pros:
Cons: