Python DISCUSSION

UnboundLocalError: why can my Python function read a global variable but not increment it?

Started by abhishek UnboundLocalErrorglobal keywordvariable scopenonlocalLEGB rule
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

UnboundLocalError: why can my Python function read a global variable but not increment it?

abhishek Python Forum
#1

At the top of my script I have count = 0. A function that does print(count) works. A callback that does count += 1 fails with UnboundLocalError, saying the local variable is referenced before assignment. Strangely, even a print(count) on the line before the increment fails once the increment is in the function.

Why does adding an assignment later in the function break an earlier read, and what is the right way to keep a counter that a callback updates?

Community replies 4

Re: UnboundLocalError: why can my Python function read a global variable but not increment it?

#2

Whether a name is local is decided when the function is compiled, for the whole function, not line by line. If the body contains any assignment to a name, including +=, a for target, an import or with ... as, that name is local everywhere in the function unless it is declared global or nonlocal.

So with count += 1 in the body, count is a local variable from the first line. The earlier print(count) reads the local, which has no value yet, and that is the UnboundLocalError. Without any assignment the lookup goes through local, enclosing function, module global and built-in scopes in that order and finds the module-level count.

Re: UnboundLocalError: why can my Python function read a global variable but not increment it?

#3

The direct fix is global count as the first line of the function. Then count += 1 reads and rebinds the module-level name.

The declaration is only needed for rebinding. Mutating a global object needs nothing: with stats = {"count": 0} at module level, stats["count"] += 1 inside a function works, because the name stats is only read and the dict it refers to is modified in place. The same holds for samples.append(x) on a global list. For nested functions the matching keyword is nonlocal: a closure that counts calls needs nonlocal n before n += 1 in the inner function.

Re: UnboundLocalError: why can my Python function read a global variable but not increment it?

#4

For callbacks it is cleaner to avoid the module global and keep the state in an object: a class Counter with self.count = 0 in __init__ and a method def on_event(self, *args): self.count += 1. Pass the bound method counter.on_event as the callback. A bound method carries its instance with it, so you can have several independent counters and a test can create its own.

When a library calls the callback with fixed arguments and you need to hand it extra state, functools.partial(handler, state) does that without a class.

Re: UnboundLocalError: why can my Python function read a global variable but not increment it?

#5

Other faces of the same rule. With x = 10 at module level, def f(): x = 20 raises no error, but the global stays 10, because the function created a separate local. And a global belongs to one module: from config import count copies the current binding into your module, so a later rebinding of config.count is not seen through your name. Use import config and read config.count to share a value that changes.

If the callback runs in another thread, as with GUI toolkits and timers, count += 1 is not atomic; guard it with a threading.Lock or pass events through a queue.Queue. In MicroPython interrupt handlers the same global declaration is used, and the handler should do little more than set a flag or bump a counter.

TEP COMMUNITY