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
).