Zafer Khourdaji
Zafer Khourdaji

Reputation: 81

UnboundLocalError: local variable 'len' referenced before assignment

print "welcome to the average finder"
print """Insert the values you want to find the average for,
when you insert all the values type 'done'"""

values = []

def insert_values():
    action = raw_input("> ")

    if 'done' in action :
        calculating_average()
    elif action != 'done':
        x = int(action)
        values.append(x)
        insert_values()
    else:
        print "please insert values then type done"
        insert_values()

def calculating_average():

    len = len(values)
    sum = sum(values)

    final = sum / len 
    print final

insert_values()

Purpose of this script: is to ask the user for numbers, then let the script find the average of the numbers and display it. I made an empty list called values, I append the user input numbers after turning them into integers.

I keep getting UnboundLocalError: local variable 'len' referenced before assignment... even thought I did assign len and sum to the length and sum of the elements in the list.

P.S. I am new to python and usually when I get an error I try to fix it on my own or research it but for this one I really dont understand why I am getting this error... any insights would be appreciated !!

Upvotes: 4

Views: 15188

Answers (2)

paxdiablo
paxdiablo

Reputation: 882146

Regarding your code:

len = len(values)
sum = sum(values)

You probably don't want to use the same name for a variable and function(1):

>>> x = [1,2,3]

>>> len(x)
3

>>> len = len(x)
>>> len
3

>>> len(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

In your case, the error message UnboundLocalError: local variable 'len' referenced before assignment is interesting but it's due to a specific Python feature.

Unless a variable within a function is marked global, rebinding it anywhere within a function will cause it to be treated as a local variable everywhere within that function, even before the point of rebinding.

So len = len(something) causes len to be classified as a local variable and you're therefore trying to use it (by calling it as a function) before it's been set.

To fix the problem, change your function to be something like:

def calculating_average():
    value_len = len(values)
    value_sum = sum(values)
    final = value_sum / value_len 
    print final

As a final note, I see two other potential problems. The first is the divide-by-zero error you'll get if you enter no numbers (i.e., enter done immediately).

The second is the ... unusual ... use of recursion to go back and get the next number. I would seriously consider refactoring your code so that this is done with a loop.


(1) At some point, every Python developer has the epiphany of the "name/object distinction".

By that, I mean that every object in Python is inherently "unnamed" and we bind to them in various ways. When the last binding is removed from an object, it becomes inaccessible and therefore subject to disposal (garbage collection). For example, the code:

a = [1, 2, 3]
b = a

creates two names but only one object, meaning a[1] = 42 will affect both the a and b "names" because the same object is bound by both:

  a   b
   \ /
    V
    [1, 42, 3]

This is what causes the issue with a statement like len = len(x).

Before you execute that, the len name is bound to a function that does what you'd expect, working out the length of some object. After execution, it's bound to the value that was returned from that function.

At that point, executing something = len(something_else) is no different to something = 3(something_else).

And also note that "binding" in this sense is mode than just name binding like name = some_object. It also includes "anonymous" bindings like my_list.append(42) - each entry in the list is a binding to the object at that position (in this case, my_list[-1] is bound to the object 42).

Upvotes: 7

claupa
claupa

Reputation: 86

The problem occurs when you create a local variable using the same name of a global function. Python assumes that there is a local variable called len that overwrites the len built-in function.

To fix this, you should add the line global len(and global sum too) before creating the len variable.

For more on Global vs Local Variables you should visit: http://www.python-course.eu/global_vs_local_variables.php

However you shouldn't name your variable as the built-in function len.

Upvotes: 2

Related Questions