@@ -7,7 +7,7 @@ The `globals()` and `locals()` functions return dictionary representations of th
77| Operation | Time | Space | Notes |
88| -----------| ------| -------| -------|
99| ` globals() ` | O(1) | O(1) | Returns reference to existing global dict |
10- | ` locals() ` | O(m) | O(m) | Creates snapshot copy; m = number of local vars |
10+ | ` locals() ` | O(1) or O( m) | O(1) or O( m) | Module/class scope is O(1); optimized function scopes materialize locals mapping |
1111| Accessing dict value | O(1) avg | O(1) | Dict key lookup; O(n) worst case with collisions |
1212
1313## Understanding Namespaces
5454y = 20
5555z = 30
5656
57- all_vars = globals () # O(n )
57+ all_vars = globals () # O(1 )
5858
5959# Filter variables (not functions/modules) - O(n)
6060my_vars = {k: v for k, v in all_vars.items()
@@ -113,7 +113,7 @@ caller()
113113### Module Level
114114
115115``` python
116- # At module level, locals() == globals() - O(n )
116+ # At module level, locals() == globals() - O(1 )
117117X = 100
118118
119119print (locals () is globals ()) # True at module level
@@ -249,7 +249,7 @@ print(task())
249249### Configuration Registry
250250
251251``` python
252- # Use globals() as simple registry - O(n)
252+ # Use globals() as simple registry - O(1) per lookup/update
253253CONFIG = {}
254254
255255def register_config (name , value ):
@@ -286,13 +286,16 @@ for i in range(1000):
286286### Large Namespaces
287287
288288``` python
289- # Many variables = expensive globals() call - O(n)
290- # In interactive session with many variables
289+ # globals() remains O(1) regardless of namespace size
290+ # Iterating over the returned dict is O(n)
291291for i in range (10000 ):
292292 globals ()[f ' var_ { i} ' ] = i # O(1) each
293293
294- # Now globals() is O(10000)
295- g = globals () # Slower!
294+ # Still O(1): returns the same global dict object
295+ g = globals ()
296+
297+ # Iteration scales with number of entries - O(n)
298+ names = [k for k in g if k.startswith(" var_" )]
296299
297300# Prefer dict for custom data
298301my_data = {}
@@ -347,13 +350,14 @@ print(obj.x) # 10
347350## Debugging with Frame Inspection
348351
349352``` python
350- import sys
353+ import inspect
351354
352355def get_caller_info ():
353356 """ Get information about calling function"""
354- frame = sys.exc_info()[2 ] # O(1)
357+ current = inspect.currentframe() # O(1)
358+ frame = current.f_back if current is not None else None # O(1)
355359 if frame is None :
356- frame = sys.gettrace().f_back # O(1)
360+ return None
357361
358362 # Access caller's locals - O(m)
359363 locals_dict = frame.f_locals
@@ -373,7 +377,7 @@ def example():
373377
374378- ** Python 2.x** : Same behavior
375379- ** Python 3.x** : Same behavior
376- - ** All versions** : O(1) for globals() (returns reference), O(m) for locals() (creates copy)
380+ - ** All versions** : ` globals() ` is O(1); ` locals() ` semantics are scope- and implementation-dependent
377381
378382## Related Functions
379383
@@ -386,14 +390,12 @@ def example():
386390✅ ** Do** :
387391
388392- Use ` globals() ` for metaprogramming when needed
389- - Cache globals() if calling multiple times
390393- Use inspect module for reflection
391394- Be explicit about variable scope
392395
393396❌ ** Avoid** :
394397
395398- Relying on locals() to set variables in functions
396- - Calling globals() in loops (cache it)
397399- Modifying globals() at module level (confusing)
398400- Using globals()/locals() instead of proper parameters
399401- Assuming locals() state persists after function returns
0 commit comments