Reputation: 176
Consider this function:
def g():
x = []
def f():
x.append([0])
print(x)
pass
return f
Calling it:
test = g()
test()
I get the following output:
Out: [[0]]
We can reinitialize the test function and call it multiple times:
test = g()
for i in range(3):
test()
Resulting in the following output:
Out: [[0]]
[[0], [0]]
[[0], [0], [0]]
However, defining the following function:
def j():
x = 1
def f():
x += 1
print(x)
pass
return f
And calling it:
test = j()
test()
Results in an error:
UnboundLocalError: local variable 'x' referenced before assignment
The list seems to be in the inner function scope while the value is not. Why is this happening?
Upvotes: 0
Views: 71
Reputation: 1526
@rassar clearly explained the reason. Here I give a solution:
def j():
x = 1
def f():
nonlocal x
x += 1
print(x)
pass
return f
Actually this is not a simple question. Even though +=
looks like a bounded method call, an in-place operation (if you have experience in other languages). But what runs under is something like x = x.__add__(1)
or x = x.__iadd__(1)
. So this is an assignment.
Upvotes: 1
Reputation: 433
Because, the python complier knows that the variable 'x' in function f is a local variable not in the function j. So the error you mentioned above is occurred.
So you should use nonlocal. Please refer the link below. Accessing parent function's variable in a child function called in the parent using python
Upvotes: 0
Reputation: 5670
This is because j
uses an assignment expression, where g
uses a method call. Remember that x += 1
is equivalent to x = x + 1
. If you change g
to:
def g():
x = []
def f():
x += [[0]]
print(x)
pass
return f
You get:
>>> test = g()
>>> test()
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
test()
File "<pyshell#18>", line 5, in f
x += [[0]]
UnboundLocalError: local variable 'x' referenced before assignment
Upvotes: 1