Reputation: 17589
I am trying to understand how closure works in Python.
I feel like add1 should work just fine here. I would expect the variable x
to have been defined when helper
is called. However, it is giving me a Local variable referenced before assignment
error.
add2
is very similar to add1
. Instead of assigning x with an integer, it assigns it with a dictionary. The behavior of it is also aligned with what I would expect. x
is defined and reference-able inside helper
.
import random
def add1():
x = 0
def helper():
x = x + 1
return x
return helper
def add2():
x = {}
def helper():
x[random.randint(1,1000)] = 3
return x
return helper
if __name__ == '__main__':
a1 = add1()
a2 = add2()
# print(a1()) #This causes error
print(a2()) #{650: 3}
print(a2()) #{650: 3, 333: 3}
What's the logic behind this? What am I doing differently other than that the types of x
are different?
Upvotes: 23
Views: 5560
Reputation: 798606
You're expecting the compiler to know that the variable has been bound outside the closure. This is not true, and hence you need to use nonlocal
to indicate this.
def add1():
x = 0
def helper():
nonlocal x
x = x + 1
return x
return helper
EDIT By denniss:
nonlocal
is not necessary in add2
because it's just modifying x
and not re-binding it (aka not re-assigning it). Whereas in add1
, x= x+1
is a re-assignment
.
Upvotes: 46