Wednesday, February 10, 2021

Closures in Python3

Let's write a closure that implements the behavior of a simple counter.

def create_counter():
    value = 0
    def counter(x):
        nonlocal value
        value += x
        return value
 
    return counter
 
c1 = create_counter()
c2 = create_counter()
 
print(c1(3))
print(c1(4))
print(c2(1))
print(c2(7))


The only non-obvious thing here, is the use of the nonlocal statement. Without using the nonlocal statement, we would get the following error:

UnboundLocalError: local variable 'value' referenced before assignment

The reason for this is:

"...the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope."

See https://docs.python.org/3/reference/simple_stmts.html#nonlocal