I don't quite understand how closure works in Python. It behaves in an unexpected way that I can't comprehend.
def A():
b = 1
def B():
b += 1
return b
return B()
print(A())
This results in an UnboundLocalError: local variable 'b' referenced before assignment.
But b
is in fact in the closure of B, as followed example works just fine.
def A():
b = 1
def B():
return b + 1
return B()
print(A())
So in my mind the closure of B has environment {b -> 1} created at the time of declaration of B. Why can't I update it locally?
The information in Patrick Roberts comment pretty much covers it.
But to be more clear, an inner function can read a variable from an enclosing scope, but can't write to it unless you've declared the variable to already exist (nonlocal or global keywords). Otherwise writing to a variable implicitly declares it local, and in the case of b += 1 tries to read an uninitialized local variable to add 1 to it, which fails.
As for why, when a local value is captured it becomes a constant, which allows inner functions to be constructed with different values. For example:
def f(x):
def g():
print(x)
return g
print_yes = f('yes')
print_no = f('no')
Calling print_yes()
will always print "yes", Calling print_no()
will print "no", even though parameter x
no longer exists.