UnboundLocalError: local variable referenced before assignment

So that sucks

Howdya fix that?

I’ll tell you. First, a simple example of the problem:

#This is valid python 2.5 code
#My global variable:
USER_COUNT = 0

#functions:
def Main():
  AddUser()

def AddUser():
  print 'There are',USER_COUNT,'users so far'

# actually run Main()
Main()

^ That program WORKS FINE. Function AddUser() just references the USER_COUNT variable, which was declared as a global (outside of any of the function blocks).

Here’s where it goes wrong: when we try to write to or we try to update the value of the global variable

#USER_COUNT is a GLOBAL variable
USER_COUNT = 0

def Main():
  AddUser()

def AddUser():
  USER_COUNT = USER_COUNT + 1
  print 'There are',USER_COUNT,'users so far'

Main()

Then we get: UnboundLocalError: local variable ‘USER_COUNT’ referenced before assignment

So that sucks.

The reason this happens is because AS SOON AS YOU WRITE TO A VARIABLE, that variable is AUTOMATICALLY considered LOCAL to the function block in which its declared. Namely:

#USER_COUNT is a GLOBAL!
USER_COUNT = 0

def AddUser():
  USER_COUNT = USER_COUNT + 1
  print 'There are',USER_COUNT,'users so far'

EVEN THOUGH we declared USER_COUNT as a GLOBAL, the simple act of WRITING TO IT __ANYWHERE__ in the function scuzzles-up the “globalness” of the USER_COUNT variable, and like, automatically makes ANY use of USER_COUNT refer to a LOCAL VARIABLE inside of AddUser().

So howdya fix it?

Easy! You do this:

#global
USER_COUNT = 0

def Main():
  AddUser()

def AddUser():
  global USER_COUNT ######!!! IMPORTANT !!!  Make sure
  # to use the GLOBAL version of USER_COUNT, not some
  # locally defined copy of that.  I think this
  # might be a python feature to stop functions from
  # clobbering the global variables in a program
  USER_COUNT = USER_COUNT + 1
  print 'There are',USER_COUNT,'users so far'

Main()

This is an ok-nice feature that might stop a program’s functions from clobbering the globals (since you really have this “just use it” attitude to a variable and you may have no clue that you’re clobbering a global), but really it might be nice if python were more consistent and required use of this global thing for BOTH read/write. Though I guess it could be kinda convenient behavior .. I don’t know yet, haven’t programmed in python for long enough.

4 Comments

  1. Addendum: Looks like I am not the only person who this surprises.

    …before the “if” statement… but I don’t understand why. Is the
    > interpreter scanning my entire function definition before executing
    > it, recognizing that I *might* assign COLUMNS to a value, and deciding
    > that it’s a local on that basis?

    You name it. That’s *exactly* what happens.

    • Anonymous
    • Posted April 3, 2009 at 10:38 pm
    • Permalink

    This was a very helpful explanation for the precise problem I was having. Thanks!

    • Anonymous
    • Posted April 9, 2009 at 9:25 pm
    • Permalink

    This solved my problem. Thanks!

    • AKMapGirl
    • Posted June 23, 2009 at 8:32 pm
    • Permalink

    Thank you so much for posting this!! Exactly the issue I was facing; now on to the next one! :)


Post a Comment