Why is the following code invalid:
def foo1(x=5):
def bar():
if x == 5:
x = 6
print(x)
bar()
While this code is valid:
def foo2(x=5):
def bar():
if x == 5:
print('ok')
print(x)
bar()
foo2() will do exactly what you expect, but foo1() will give a UnboundLocalError: local variable 'x' referenced before assignment at the line if x == 5:. Why does altering the value of x later on in the code make this conditional invalid?
Python needs first to detect what variables are local, and which variable are fetched from an outer scope. In order to do that it looks for assignments, like:
def foo1(x=5):
def bar():
if x == 5:
x = 6 # an assignment, so local variable
print(x)
bar()
The point is, that the assignment can happen anywhere. For instance on the last line. Nevertheless, from the moment there is an assignment somewhere x is local. So in your first code fragment, x is a local variable. But you fetch it before it is assigned (bounded), so Python will error on it.
In python-3.x you can use the nonlocal keyword to access x from an outer scope:
def foo1(x=5):
def bar():
nonlocal x
if x == 5:
x = 6
print(x)
bar()
For python-2.x, you can for instance assign the variable to the function, like:
def foo1(x=5):
def bar():
if bar.x == 5:
bar.x = 6
print(bar.x)
bar.x = x
bar()
Note however that the two are not equivalent. Since in the former if you alter x, it will be alter the x in the foo1 scope as well. In the latter example you only modify bar.x. Of course if these are mutable objects, you alter the same object.
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