Technical skill practice
Global Variable in Python: Read, Shadow and Rebind a Counter
A Python function can read a module-level variable without declaring global. Assigning to a name inside the function normally makes it local there. Use global only when the function intends to rebind that module-level name; an explicit parameter and return value often makes the dependency easier to see.
Start with a small, explicit task
Track a fictional counter through four functions: one reads it, one shadows it locally, one attempts an invalid local increment, and one explicitly changes the global binding. Finish with a pure increment that takes its starting value as an argument.
Run the complete example
This original example was checked with Python 3.12.14. Save it as python_global_variable.py and run it with Python 3.12. It uses only the standard library. The assertions check the stated results.
Expected output
11
local read before assignment
12
counter = 10
def read_counter():
return counter
def shadow():
counter = 99
return counter
def bad_increment():
counter += 1
def increment_global():
global counter
counter += 1
def increment(value):
return value + 1
assert read_counter() == 10
assert shadow() == 99 and counter == 10
try:
bad_increment()
except UnboundLocalError:
failure = "local read before assignment"
else:
raise AssertionError("expected UnboundLocalError")
increment_global()
assert counter == 11
assert increment(counter) == 12 and counter == 11
print(counter)
print(failure)
print(increment(counter))
Explain the result
shadow returns its own local value without changing the module counter. In bad_increment, the augmented assignment makes counter local, but the operation tries to read that local value before it has been assigned. This produces UnboundLocalError rather than falling back to the module value.
increment_global explicitly rebinds the module name and changes it to 11. The parameter-based increment calculates 12 without changing counter, so the caller decides whether to retain or assign the result. That difference is useful when reasoning about tests or multiple callers: the inputs to the pure calculation are visible in its call.
Avoid these mistakes
Do not add global merely to silence a scope error without deciding who should own the state. global also does not make shared mutation safe across threads or processes. nonlocal is a separate tool for an enclosing function scope, not a synonym for module-level assignment.
Questions, answered
Do I need global to read a module variable?
Not in read_counter here. The declaration is relevant when rebinding that module-level name inside the function.
Why does += raise UnboundLocalError?
The function treats counter as local, then tries to read it before a local value exists.
Sources and examples
ResumizeAI team. Examples are fictional teaching material, not customer results. Replace sample details with your own facts.
Your experience. A complete resume.
Build in Resumize with ATS-friendly templates, guided editing and a live preview. Start free, then upgrade when you need more.
Free account required. Free-plan PDF exports include a watermark.