What do the global and nonlocal keywords do, and when should you use them?
global declares that a name inside a function refers to the module-level variable, allowing reassignment. nonlocal does the same for the nearest enclosing function scope. Both should be used sparingly — they make control flow harder to reason about, and a class or closure that returns a value is usually a cleaner design.
How to think about it
Both keywords sit on top of Python’s name-resolution order, LEGB — Local, Enclosing, Global, Built-in. By default, any name on the left of = inside a function becomes a new local for the whole body. global and nonlocal override that: they tell Python “don’t make a new local — rebind the one that already lives further out.”
Built-in (len, print, …)
▲
Global (module level) ← `global` targets here
▲
Enclosing (outer function) ← `nonlocal` targets here
▲
Local (current function) ← the default for any assignment
The follow-up interviewers actually care about is when not to use them — and the honest answer is “almost never; a class or a value-returning closure is usually cleaner.”
global — rebind a module-level name
_cache = {}
def fetch(key):
global _cache
if key not in _cache:
_cache[key] = key.upper() # a stand-in for an expensive lookup
return _cache[key]
A subtlety worth stating: mutating _cache[key] = ... never needed global at all — mutation isn’t rebinding. You only need global if you intend to reassign the name itself (say _cache = {} to reset it); without it, that line would create a local shadow and leave the module cache untouched.
nonlocal — rebind an enclosing name
def make_counter(start=0):
count = start # lives in make_counter's frame
def increment(step=1):
nonlocal count # rebind count in the enclosing frame
count += step
return count
def reset():
nonlocal count
count = start
def current():
return count # read-only — no nonlocal needed
return increment, reset, current
inc, rst, cur = make_counter(10)
print("inc() :", inc())
print("inc(5) :", inc(5))
print("cur() :", cur())
rst()
print("after rst:", cur())
# Each call to make_counter gets its OWN frame — no shared state
c1_inc, _, c1_cur = make_counter(0)
c2_inc, _, c2_cur = make_counter(100)
c1_inc(); c1_inc(); c2_inc(50)
print("c1 =", c1_cur(), "c2 =", c2_cur())
inc() : 11
inc(5) : 16
cur() : 16
after rst: 10
c1 = 2 c2 = 150
increment and reset both rebind count in the enclosing frame, while current only reads it and so needs no declaration. And the last line is the reassuring part: two counters built from the same factory keep entirely separate state, because each make_counter call owns its own frame.
The cleaner alternatives
global and nonlocal are worth knowing but should make you pause before using. The same state usually reads better as:
- a class —
__init__plus methods; state is explicit and testable; - a returned value — the caller holds the state and your functions stay pure;
- a mutable container in the enclosing scope — mutating a
listordictneeds nononlocal(just mind the mutable-default trap).
One mechanical difference to keep straight: nonlocal requires the name to already exist in an enclosing scope, while global can create a module-level name that didn’t exist yet.