If you assign a value to a variable anywhere inside a function, Python assumes that variable is local to that function. So even if there’s a global variable with the same name, Python won’t look at it. It treats your variable as a separate, uninitialized local one. That’s why you get the error when you try to use it before assigning a value.

Want to fix it? You’ve got two options:

  • If you really want to use the global variable, add global variable_name inside the function.
  • Or better yet, avoid this pattern. It’s often cleaner to pass variables into functions and return new values.

Description of the Problem

You’re using a global variable inside a function, but Python throws this error:

counter = 10
def increment(): counter += 1 print(counter)
increment()

Output:

UnboundLocalError: local variable 'counter' referenced before assignment

You’re confused — counter is clearly defined at the top level. Why is Python treating it like it’s undefined inside the function?

Why This Happens

This error occurs when you try to modify a global variable without declaring it as global inside a function. In Python, when you assign a value to a variable anywhere inside a function, Python treats it as a local variable unless explicitly told otherwise.

So in this line:

counter += 1

Python treats counter as a new local variable. But since it hasn’t been assigned before that line, it throws an UnboundLocalError.

Even though counter exists globally, Python doesn’t look at that definition because it assumes you’re trying to create a new local variable.

How to Resolve the UnboundLocalError in 3 Simple Steps

Step 1: Use the global keyword if you want to modify the global variable

To tell Python that you’re referring to the global counter, use the global keyword:

counter = 10
def increment(): global counter counter += 1 print(counter)
increment() # Output: 11

Now Python knows you’re not creating a new local variable — you’re modifying the global one.

Step 2: Avoid global when possible – prefer return values

Using global can make code harder to debug and maintain. Instead, consider returning values and reassigning them:

def increment(counter): counter += 1 return counter
counter = 10
counter = increment(counter)
print(counter) # Output: 11

This makes data flow clear and avoids side effects.

Step 3: Use nonlocal for modifying variables in nested functions

If you’re working with nested functions and want to modify a variable from the enclosing scope (but not global), use nonlocal:

def outer(): counter = 0 def inner(): nonlocal counter counter += 1 print(counter) inner() inner()
outer()

This modifies counter in the outer() function, not the global scope.

Best Practices:

  • Use the global keyword if you must modify a global variable
  • Prefer passing and returning variables to avoid using global
  • Use nonlocal for modifying variables in nested scopes (closures)

Understanding Python’s scoping rules—Local, Enclosing, Global, and Built-in (LEGB)—is key to avoiding bugs like UnboundLocalError.

Conclusion

Understanding Python’s scoping rules can save you from frustrating bugs like UnboundLocalError. If you’re building complex Python applications and want to get things right from the start, it might be time to hire Python developers who understand these subtleties. A slight change in scope can create big problems if you’re not careful.