I have some code from a beginner's coding exercise:
numbers = []
i = 0
def populate(maximum, step):
while i < maximum:
numbers.append(i)
i = i + step
populate(10, 2)
Which fails with the stack trace:
Traceback (most recent call last):
File "test_python.py", line 9, in <module>
populate(10, 2)
File "test_python.py", line 5, in populate
while i < maximum:
UnboundLocalError: local variable 'i' referenced before assignment
Here is my understanding of the problem so far...
iis an int and therefore it is immutable, andnumbersis a list and is mutable- Since
iis immutable, it can be read while it is out of scope. However, overwritting it while it is not in scope (ie. in thepopulatefunction), causes anUnboundLocalError - Since
numbersis a mutable list, appending to it does not cause an overwrite and therefore does not cause anUnboundLocalError If a simple change is made to the
populatemethod, the program works successfully (due toinot being overwritten)def populate(maximum, step): new_i = i while new_i < maximum: numbers.append(i) new_i = new_i + stepIf I comment out the
i = i + 1line, the while loop (obviously) runs forever, but the program does not fail.
My question is then, why does Python fail when it hits the while loop on line 5, instead of the actual problem on line 7 (i = i + 1)? Is this some artifact of the interpreter taking the while loop as a block of code?
This piece of code fails in the correct spot:
def populate(maximum, step):
while i < maximum:
raise Exception("foo")
Stack trace:
Traceback (most recent call last):
File "test_python.py", line 12, in <module>
populate(10, 2)
File "test_python.py", line 6, in populate
raise Exception("foo")
Exception: foo
Another note: This only seems to be the case when the variable is used within the start of the control block (ie. while i < maximum). And the same behavior occurs for every type of control block: while, for, if, elif, etc.