Namespaces in Python
Namespaces in Python
Namespaces
Namespaces in Python are essential concepts that refer to a system that holds a collection of names as keys and their corresponding objects as values. They are used to organize variables and avoid conflicts by creating separate, distinct regions for different names.
In [ ]: a=2
b=3
{a:2}
{b:3}
Contains built-in functions and exceptions that come with Python, such as print() , len() , and Exception .
This namespace is loaded when the Python interpreter starts and is available globally in any part of the program.
2. Global Namespace
Contains names defined at the level of the main program, or names defined in a module imported into the main program.
Variables, functions, and classes declared outside of functions or classes are part of the global namespace.
Each module has its own global namespace.
3. Local Namespace
Created when there are nested functions. If a function is defined inside another function, it has access to the outer function’s namespace.
Variables in the enclosing function are part of the enclosing (nonlocal) namespace for the inner function.
Uses the nonlocal keyword to modify variables from the outer function scope.
In Python, local and global scopes define where variables are accessible within a program.
Local Scope
A local scope is the region within a function or block of code where variables created within that block are accessible. Variables created in a local scope are called local variables, and they only exist during the execution of that specific function.
Lifetime: Local variables are only available while the function is running and are destroyed once the function completes.
Isolation: Each function has its own local scope, so variables within one function do not affect variables within another function, even if they share the same name.
Global Scope
A global scope is the region where variables are accessible throughout the entire program, including inside and outside functions. Variables created outside of any function or block are considered global variables, and they are accessible from any function in the program unless
shadowed by a local variable of the same name.
Key Differences
1. Accessibility:
def temp():
b=3 #local variable
print(b)
temp()
print(a)
3
2
def temp():
a=3 #local variable
print(a)
temp()
print(a)
3
2
In [4]: # local and global -> local does not have but global has
def temp():
print(a)
temp()
print(a)
2
2
def temp():
#local var
a+=1
print(a)
temp()
print(a)
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
Cell In[5], line 8
5 a+=1
6 print(a)
----> 8 temp()
9 print(a)
UnboundLocalError: cannot access local variable 'a' where it is not associated with a value
def temp():
global a
a+=1
print(a)
temp()
print(a)
3
3
In Python, the global keyword is used to declare that a variable inside a function refers to a globally defined variable outside the function's scope. By default, when you assign a value to a variable within a function, Python treats it as a local variable. If you want to modify a global
variable inside a function, you need to declare it as global .
1. Python searches for variable_name in the global namespace instead of creating a new local variable.
2. Changes to variable_name within the function will affect the global variable outside the function.
Use global when you need to modify a global variable inside a function.
Avoid using global excessively, as it can make code harder to read and maintain by tightly coupling functions with global state.
Limitations
global cannot be used to declare variables outside of all functions in the script or module scope.
It only affects variable references within the function where it's declared, not across other modules.
def temp():
global a
a=1
print(a)
temp()
print(a)
1
1
def temp(z):
print(z)
a=5
temp(5)
print(a)
print(z)
5
5
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[13], line 7
5 temp(5)
6 print(a)
----> 7 print(z)
Built-in Scope
The built-in scope in Python is the outermost scope where Python's built-in functions, constants, and exceptions reside. This includes functions like print() , len() , sum() , and constants such as True , False , and None . The built-in scope is part of Python's standard library,
and the objects defined in it are available globally in any Python script or module.
2. Immutability: Since the built-in scope is defined when Python starts up, objects in this scope are essentially immutable for practical purposes, meaning they should not (and usually cannot) be redefined. However, technically, if you assign True = False , Python will allow it, but
this will cause severe bugs and break the program's logic.
3. Namespace Hierarchy: Python resolves variable names by looking up the namespace hierarchy: local → enclosing → global → built-in. If a name isn’t found in the local, enclosing, or global scope, Python finally checks the built-in scope.
print("hello")
hello
import builtins
print(dir(builtins))
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BaseExceptionGroup', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'Conn
ectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EncodingWarning', 'EnvironmentError', 'Exception', 'ExceptionGroup', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'Fu
tureWarning', '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', 'ResourceWarnin
g', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'Unic
odeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__IPYTHON__', '__build_class__', '__debug__', '__doc__', '__import__', '__loader_
_', '__name__', '__package__', '__spec__', 'abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'd
ict', 'dir', 'display', 'divmod', 'enumerate', 'eval', 'exec', 'execfile', 'filter', 'float', 'format', 'frozenset', 'get_ipython', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclas
s', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'range', 'repr', 'reversed', 'round', 'runfile', 'set', 'setattr', 'slice', 'sorte
d', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
len = 5
print(len([1, 2, 3])) # This will raise a TypeError because `len` is now an integer, not a function
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[1], line 5
1 ### Modifying Built-in Scope (Not Recommended)
2
3 # Don't do this!
4 len = 5
----> 5 print(len([1, 2, 3]))
In [22]: # Avoid naming your variables after built-in functions or constants to prevent accidental overrides.
L=[1,2,3]
max(L)
def max():
print("hello")
max(L)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[22], line 4
1 #rename built-ins
3 L=[1,2,3]
----> 4 max(L)
6 def max():
7 print("hello")
Enclosing Scope
The enclosing scope in Python refers to the scope of any outer, or "enclosing," function within which a nested (inner) function is defined. This is sometimes also called the "nonlocal" scope. When an inner function tries to access a variable that isn’t defined locally, Python will check the
enclosing function’s scope to resolve the variable before moving on to the global or built-in scopes.
def outer():
def inner():
print(a)
inner()
print("outer function")
outer()
print("main program")
1
outer function
main program
def outer():
def inner():
print(a)
inner()
print("outer")
#b=1
outer()
print("main program")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[29], line 12
9 print("outer")
11 #b=1
---> 12 outer()
13 print("main program")
Here, nonlocal allows inner_function to modify the message variable from outer_function . Without nonlocal , assigning a new value to message inside inner_function would create a new local variable named message without affecting the enclosing scope.
def outer():
a=1
def inner():
nonlocal a
a+=1
print("inner",a)
inner()
print("outer",a)
#b=1
outer()
print("main program")
inner 2
outer 2
main program