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?
The Python "UnboundLocalError: Local variable referenced before assignment" occurs when we reference a local variable before assigning a value to it in a function. To solve the error, mark the variable as global in the function definition, e.g. global my_var .
UnboundLocalError can be solved by changing the scope of the variable which is complaining. You need to explicitly declare the variable global. Variable x's scope in function printx is global. You can verify the same by printing the value of x in terminal and it will be 6.
Closures are elegant Python constructs. In this article, we'll learn about them, how to define a closure, why and when to use them. But before getting into what a closure is, we have to first understand what a nested function is and how scoping rules work for them.
The UnboundLocalError: local variable referenced before assignment error is raised when you try to assign a value to a local variable before it has been declared. You can solve this error by ensuring that a local variable is declared before you assign it a value.
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
.
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