Possible Duplicate:
referenced before assignment error in python
I'm getting a strange error in python. The following ipython log sums it up:
In [10]: def confused(stuff):
....: print huh
....: return stuff
....:
In [11]: confused(87)
0
Out[11]: 87
In [12]: def confused(stuff):
....: print huh
....: huh += 1
....: return stuff
....:
In [13]: confused(9)
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
/home/max/verk/btr-email/build/x86_64/bin/ipython in <module>()
----> 1 confused(9)
/home/max/verk/btr-email/build/x86_64/bin/ipython in confused(stuff)
1 def confused(stuff):
----> 2 print huh
3 huh += 1
4 return stuff
UnboundLocalError: local variable 'huh' referenced before assignment
The only difference between the function that works and the one that throws an error is the +=1 line, and even then, it throws an error on a line which was previously working! It also doesn't throw an error if I put global huh
before referencing huh
in the 2nd version of the method.
Why does adding a line where I add one to the variable suddenly change it from a global to a local variable?
In your script, huh
refers to a global variable. You can't change the reference to a global variable in a function without explicitly telling python that is what you want to do:
def confused(stuff):
global huh
print huh
huh += 1
return stuff
For immutable objects like ints, strings, floats, etc, that means that you can't make any changes to the object without declaring it as global
. For mutable objects, you can make changes to the objects items or attributes, but you still can't change the object's reference.
This is all a question of scope. since huh
isn't in the local scope of confused
, python finds it in the global scope. Since it is found in the global scope, you can't assign to it unless you specifically say that you want to (using global
as I have done above). However, if it's a list
, once the list is found, you have access to all of that list's methods (including __setitem__
, append
, etc.)
As to the location of the error, this can be cleared up with a little dis
assembling:
>>> def confused(stuff):
... print huh
...
>>> import dis
>>> dis.dis(confused)
2 0 LOAD_GLOBAL 0 (huh)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
>>> def confused2(stuff):
... print huh
... huh += 1
...
>>> dis.dis(confused2)
2 0 LOAD_FAST 1 (huh)
3 PRINT_ITEM
4 PRINT_NEWLINE
3 5 LOAD_FAST 1 (huh)
8 LOAD_CONST 1 (1)
11 INPLACE_ADD
12 STORE_FAST 1 (huh)
15 LOAD_CONST 0 (None)
18 RETURN_VALUE
You can see that in confused2
, python is already trying to LOAD_FAST
(meaning, look for a local variable) at the first line of the function. However, no local variable huh
exists hence the Exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With