Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

Why does a function raise UnboundLocalError for a name that exists globally?

Quick answer

If a function assigns to a name anywhere in its body, Python treats that name as local throughout the function unless you declare it global or nonlocal. Reading it before assigning it locally can therefore raise UnboundLocalError, even when a global with the same name exists. [S1] Rename the local variable, pass the value in and return an updated value, or explicitly declare global when you intend to rebind the module-level name.

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

Why does this fail if count is already defined outside the function?

count = 10

def add_one():
    count += 1
    return count

add_one()

Geez

The assignment is the key. Python treats a name bound anywhere in a function as local throughout that function, unless it is declared global or nonlocal. So count += 1 tries to read the function’s local count before that local has a value; the global count does not supply it. That read-before-local-binding situation raises UnboundLocalError. [S1]

For a minimal reproduction, the example you posted is enough: the global value exists, but the function’s own binding decision makes the attempted read local. The error is about scope, not whether the module-level variable was created.

Follow-up question

How can I confirm that the assignment is what changes Python’s decision?

Geez

Temporarily remove the assignment and read the name:

count = 10

def show_count():
    return count

print(show_count())  # 10

With no binding of count in show_count, the function can use the global name. Add an assignment to that same name anywhere in the function, even below a read, and Python treats it as local throughout the function unless you declare otherwise. [S1]

For example, this still fails on the first line of the function body:

def show_then_change():
    print(count)
    count = 11

The later assignment matters when Python determines the name’s scope; it does not make the earlier read use the global.

Follow-up question

What should I change if I want to calculate a new value without modifying the global?

Geez

Use a different local name, or pass the starting value in and return the result. These approaches make the data flow explicit and avoid rebinding the global:

count = 10

def next_count(current):
    updated = current + 1
    return updated

count = next_count(count)

Here current is the function’s input and updated is its local result. The caller decides whether to store that result back in count. If the calculation is only for display or another operation, keep the returned value in a different caller-side name instead:

new_count = next_count(count)

Follow-up question

When is global appropriate, and how do I avoid choosing it by habit?

Geez

Use global only when rebinding the module-level name from inside the function is intentional. For example:

count = 10

def add_one():
    global count
    count += 1
    return count

The declaration directs uses of count in that function to the module-level namespace. [S1] If you mean a name in an enclosing function instead, nonlocal refers to a previously bound name in the nearest enclosing function scope; it does not refer to a module global. [S1]

Before adding either declaration, ask whether the function should instead take an input and return a result. That option usually makes it clearer where the value comes from and where the change is used. The cited language reference explains the scope rule, but it does not prescribe which design is best for your particular program.

A practical checklist

  • Find every assignment to the name inside the function, including augmented assignments such as +=.

  • Check whether the function reads that name before its local assignment.

  • If the function should calculate a result, pass in the value and return the result.

  • If rebinding an outer name is deliberate, choose global for a module name or nonlocal for an enclosing function binding.

  • Run the smallest example that reproduces the error, then verify the chosen fix in the surrounding code.

A few more useful answers

Does assigning to the name later in the function make an earlier read use the global?

No. A binding anywhere in the function makes the name local throughout that function unless declared global or nonlocal, so an earlier read can raise UnboundLocalError. [S1]

Can `nonlocal` fix this when the value is defined at module level?

No. nonlocal refers to a previously bound name in an enclosing function scope, not a module global. Use global only if you intend to rebind the module-level name. [S1]

What is a simple alternative to changing a global inside a function?

Pass the current value as an argument, calculate a local result, and return it. The caller can decide whether to replace its existing value or keep the result separately.

Sources

References used for this guide.

  1. [S1] Python 3.14 Language Reference: Execution model — Naming and binding
    docs.python.org · Checked

YOUR QUESTION. YOUR DETAILS.

Let’s work through your situation.

Get a tailored answer or help with your next task. Starts at $1, with a quote before you pay.

Ask your own question
← Back to Geez at Work