Working with Captured Variables in Python Closures
Saturday April 25, 2015
You can make closures in Python like this:
def add_some(x=0):
def adder(y):
return x+y
return adder
add3 = add_some(3)
print(add3(7))
## 10
The adder function "remembers" x.
But this will fail:
def a_counter(count=0):
def counter():
count += 1
return count
return counter
the_counter = a_counter()
print(the_counter())
## UnboundLocalError: local variable 'count' referenced before assignment
You can't assign to count in there!
In Python 3, you can resolve this with nonlocal:
def a_counter(count=0):
def counter():
nonlocal count
count += 1
return count
return counter
the_counter = a_counter()
print(the_counter())
## 1
print(the_counter())
## 2
print(the_counter())
## 3
Great! I'd rather not have to specify nonlocal, but I'm happy to know of another feature unique to Python 3.
In Python 2, you can't get assignment of captured variables inside your closure, but you can mutate a captured variable. ¯\_(ツ)_/¯
def a_counter(count={'val': 0}):
def counter():
count['val'] += 1
return count['val']
return counter
the_counter = a_counter()
print(the_counter())
## 1
print(the_counter())
## 2
print(the_counter())
## 3
Hooray for closures!