0

file1.py:

a = 2;

class adder():

    def __init__(self):
        a = a;
        a = a % 5;
        print a;

Instantiating adder() results in "UnboundLocalError: local variable 'a' referenced before assignment," but if I change init to:

def __init__(self):

     print a;

then I get no errors.

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
user49404
  • 732
  • 6
  • 22
  • Plus one for the fun question. – Russia Must Remove Putin Jan 20 '15 at 00:57
  • 2
    This is such a frequent gotcha that it even [gets a mention in the official docs](https://docs.python.org/2/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value) – zehnpaard Jan 20 '15 at 00:58
  • 1
    The `UnboundLocalError` is covered here: http://stackoverflow.com/questions/9264763/unboundlocalerror-in-python and [in the Python FAQ here](https://docs.python.org/3/faq/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value). – Lack Jan 20 '15 at 00:58
  • Welcome to StackOverflow, if I've answered your question, as I've attempted to give you a practical way to move forward, you can accept my answer by selecting the checkmark next to it. – Russia Must Remove Putin Jan 20 '15 at 01:10

2 Answers2

5

If a = ... (or any other form of assignment, like for a in ...) appears anywhere in the body of a function, then a becomes a local for the entire function. You can't have a variable be partly global and partly local.

So you have a local named a, and you're trying to assign a = a. The first thing Python needs to do is figure out the value of that a on the right-hand side... but a is a local that hasn't been assigned to yet. Hence the error.

Just use a different variable name. If you really really want to change the outer a (which smells fishy in a constructor!), you have to declare your intention with global a.

Also, you don't need semicolons at the end of lines in Python. And if this is Python 2, your class should inherit from object (as in class Adder(object):), else you'll get an "old-style" class which has different behavior and doesn't exist in later versions of Python.

Eevee
  • 47,412
  • 11
  • 95
  • 127
2

You need to use a global statement to pull the module-level global a variable into your scope:

a = 2

class adder():
    def __init__(self):
        global a # need this!
        # a = a # don't need this
        a = a % 5 # assigning to `a` would be otherwise ambiguous without
                  # the global statement
        print a

You don't need the semicolons.

Better is to use a default argument, something like this, to avoid changing things on the global level.:

a = 2

class adder():
    def __init__(self, a=a):
        # don't need global statement since we're going to default to 
        # the global a.
        # a = a # don't need this
        a = a % 5
        print a

Another superior approach would be to use different names on the global and local level. I would rename the global variable, and keep the local variable the same. We tend to capitalize (all caps) global constants (and capitalize class names, and inherit from object), so that might look like this:

A = 2

class Adder(object):
    def __init__(self):
        a = A % 5
        print a
Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
  • because `print a` by itself does not create a local variable, so python knows you mean the global one. When you add the assignment in python thinks you mean the local a, which isn't defined. – Tony Suffolk 66 Jan 20 '15 at 01:02