While implementing a breadth-first search routine for a graph in Python I wanted to pass in a function to get called every time a vertex is visited. After programming in JavaScript, I immediately used a closure. I hadn’t actually ever used a closure in Python before and thought that nested functions were rather ugly.

It turns out that they work mostly like closures in JavaScript with one major exception; Enclosed variables are read-only. Consequently, assigning to variable in the outer-scope creates a local alias rather than modify the outer variable. To fix this, one must declare the enclosed variable before modifying it with the nonlocal keyword.

Here is an example:

def outer():
    x = 'foo'
    print("x is {} in outer before assignment".format(x))

    def inner_local():
        x = 'bar' 
        print("x is {} in inner_local after assignment".format(x))

    inner_local()
    print("x is {} in outer after calling inner_local()".format(x))

    def inner_nonlocal():
        nonlocal x
        x = 'bar' 
        print("x is {} in inner_nonlocal after assignment".format(x))

    inner_nonlocal()
    print("x is {} in outer after calling inner_nonlocal()".format(x))

Calling outer() prints the following:

x is foo in outer before assignment
x is bar in inner_local after assignment
x is foo in outer after calling inner_local()
x is bar in inner_nonlocal after assignment
x is bar in outer after calling inner_nonlocal()