reference
3 min read
·
lesson 22 of 45 in Errors
UnboundLocalError: local variable referenced before assignment
1 · The lesson
readWhat this error means
Python decides at compile time, not run time, which names inside a function are local. If a function assigns to a name anywhere in its body, that name is local for the whole function — including lines that run before the assignment. If you read it before assigning, you getUnboundLocalError.
When you see it
text
Traceback (most recent call last):
File "counter.py", line 8, in <module>
bump()
File "counter.py", line 5, in bump
print(count)
UnboundLocalError: cannot access local variable 'count' where it is not associated with a valueThe classic minimal reproduction:
python
count = 0 def bump(): print(count) # boom: count is local, not yet assigned count = count + 1 bump()
Why it happens
Thecount = count + 1 on the last line makes count a local variable for the entire bump body. The earlier print(count) therefore looks at the local count, which has no value yet — not the module-level count = 0. Python is being consistent, not surprising: a name's scope is a property of the function, not of the line.
How to fix it
Option 1 — declare the intent with global or nonlocal. Use sparingly; mutable shared state is a smell.
python
count = 0 def bump(): global count count = count + 1
For a name in an enclosing function (not module-level):
python
def make_counter(): count = 0 def bump(): nonlocal count count += 1 return count return bump
Option 2 — pass and return instead of mutating. Cleaner, testable, no shared state.
python
def bump(count): return count + 1 count = bump(count)
Option 3 — use a mutable container. Works because you mutate the object, not rebind the name.
python
state = {"count": 0}
def bump():
state["count"] += 1 # no assignment to `state` itselfWhen you'd actually see this in real code
- A function reads a config flag, then later reassigns it for the rest of the function ("if no value passed, use default").
- A closure tries to update a counter in the enclosing scope but forgets
nonlocal. - Loop accumulators inside a function where someone "improved" the code by initialising the accumulator at the top of the module instead of inside the function.
Related errors
NameError: name 'x' is not defined— Python could not findxin any scope. Different fromUnboundLocalError, where it found a local but the local has no value yet.SyntaxError: name 'x' is used prior to nonlocal declaration— you used the name before declaringnonlocal x.
See Also
- All Python errors — the full index, by type and by when it happens.
- Functions — scope rules in depth.
- Closures — where
nonlocalmatters. - cheat-scope — LEGB lookup reminder.