Scope and namespaces
Scope is *where a name is visible*. A variable created inside a function is local — it exists only while that function runs and vanishes when it returns. Code outside can't see it. Try to use it and you get NameError: name '...' is not defined.
That's the whole point: functions are sealed boxes. To get a value out, you return it and the caller catches it — you don't reach inside.
Python resolves a name with the LEGB rule, searching outward: Local (this function) → Enclosing (a function around this one) → Global (the module/file) → Built-in (len, print, …). The first match wins.
A function can *read* a global, but to *reassign* one it needs the global keyword — otherwise the assignment just creates a new local that shadows it. global works but is usually a code smell: it makes functions depend on hidden shared state. Prefer passing values in as arguments and handing results back with return.
Syntax
x = 1 # global (module-level)
def f():
y = 2 # local — invisible outside f()
return x + y # reads global x, local y
# LEGB lookup order: Local → Enclosing → Global → Built-in
def bump():
global x # needed to REASSIGN a global (a smell)
x = x + 1Worked examples
Local stays local — return it to get it out
def calculate(a, b):
total = a + b # local to calculate
return total # hand it back
result = calculate(5, 3) # capture the return value
print(result) # 8
# print(total) → NameError: total only existed inside calculateReassigning a global needs the global keyword
counter = 0
def increment():
global counter # without this, you'd make a NEW local
counter += 1
increment()
increment()
print(counter) # 2Shadowing — a local hides the global of the same name
name = "outer"
def show():
name = "inner" # a NEW local, doesn't touch the global
return name
print(show(), name) # inner outerCommon mistakes & gotchas
Using a local outside its function
A variable assigned inside a function dies when the function returns. Referencing it at module level raises NameError. The cure is almost always return the value and capture it where you call the function.
Assigning to a global without declaring it
If a function assigns to a name anywhere in its body, Python treats that name as local for the *whole* function — even before the assignment. Reading a global then assigning to it without global gives UnboundLocalError. Declare global x (or, better, pass and return).
Reaching for global as a shortcut
global makes a function silently depend on outside state, which makes bugs hard to trace and functions hard to test. It's rarely the right tool — pass values in as parameters and return results out instead.
Why it matters
Scope is what keeps a 10,000-line program from collapsing into one giant tangle of variables stepping on each other. Each function gets its own clean namespace, so you can reason about it in isolation. Understanding LEGB turns mysterious `NameError`s and `UnboundLocalError`s into a quick, obvious fix.