Skip to content

Scope & Namespaces

Python resolves names using the LEGB rule โ€” it searches scopes in this order:

  1. Local โ€” inside the current function
  2. Enclosing โ€” any enclosing function scopes (closures)
  3. Global โ€” module-level
  4. Built-in โ€” Pythonโ€™s built-in names (len, print, etc.)
def greet():
message = "Hello" # local to greet()
print(message)
greet()
# print(message) # NameError โ€” not accessible here
app_name = "MyApp" # global
def show():
print(app_name) # reads global โ€” OK
show() # "MyApp"

Required to modify a global variable inside a function:

counter = 0
def increment():
global counter
counter += 1
increment()
print(counter) # 1
def outer():
x = 10
def inner():
print(x) # reads from enclosing scope
inner()
outer() # 10

Modifies a variable in the nearest enclosing (non-global) scope:

def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
c = counter()
print(c()) # 1
print(c()) # 2
print(c()) # 3
  • A namespace is a mapping from names to objects (like a dictionary).
  • A scope is the textual region where a namespace is directly accessible.
import builtins
# View built-in names
print(dir(builtins))
# View local/global namespaces
def demo():
local_var = 1
print(locals()) # {'local_var': 1}
print(globals()) # module-level namespace
x = 10
def bad():
print(x) # UnboundLocalError!
x = 20 # Python sees this assignment and treats x as local throughout
# Fix: use global keyword or rename the local variable

In Python 3, comprehension variables are scoped to the comprehension:

result = [i for i in range(5)]
# print(i) # NameError in Python 3 (was accessible in Python 2)