A closure is a function with an extended scope that encompasses non-global variables but not defined there. It does not matter whether the function is anonymous of not, what matters is that it can access non-global variables that are defined outside of its body.

This is a challenging concept to grasp, and is better approached through an example. Consider a avg function to compute the mean of an ever-increasing series of values. This is how avg could be used.

>>> avg(10)
10.0
>>> avg(11)
10.5
>> avg(12)
11.0

A common way to do this is implementing a class Averager.

class Averager:
    def __init__(self):
        self.sum = 0.0
        self.count = 0

    def __call__(self, v):
        self.sum += v
        self.count += 1
        return self.sum / self.count

avg = Averager()
print(avg(10), avg(11), avg(12))

A functional implementation using a higher order function is:

def makeAverager():
    series = []

    def averager(v):
        series.append(v)
        return sum(series) / len(series)

    return averager

avg = makeAverager()
print(avg(10), avg(11), avg(12))

The series is a local variable of makeAverager because the initialization series = [] happen in the body of that function. When avg(10) is called, makeAverager has already returned, its local scope is a long gone.

The closure for averager extends the scope of that function to include the binding for the free variable series.

Inspecting the returned averager object shows how Python keeps the names of local and free variables in the __code__ attribute that represents the complied body of the function:

>>> avg.__code__.co_varnames
('v',)
>>> print(avg.__code__.co_freevars)
('series',)

The binding for series is kept in the __closure__ attribute of the returned function avg. Each item is avg.__closure__ corresponds to a name in avg.__code__co_freevars. These items are cells with an attribute cell_contents where the actual value can be found.

>>> avg.__closure_
(<cell at 0x10f5e9918: list object at 0x10f8178c8>,)
>>> avg.__closure__[0].cell_contents)
[10, 11, 12]

To summarize: a closure is a function that retains the bindings of the free variables that exist when the function is defined, so that they can be used later when the function is invoked and the defining scope is no long available.

nonlocal declaration

It is not necessary to keep the historical values. A better solution is to store the total and the number of items so far.

def makeAverager():
    total = count = 0

    def averager(v):
        total += v
        count += 1
        return total / count

    return averager

avg = makeAverager()
print(avg(10), avg(11), avg(12))

Oh, UnboundLocalError! The problem is that the statement total += v means the same as total = total + v assigning to total in the body with averager which makes it local.

With immutable types like numbers, strings, tuple etc., all you can is read, but never update. If you try to rebind them, as in total += v, total is no longer a free variable, there it’s not saved in the closure.

nonlocal declaration lets you flag a variable as a free variable even when it is assigned with the function.

def makeAverager():
    total = count = 0

    def averager(v):
        nonlocal total, count
        total += v
        count += 1
        return total / count

    return averager

avg = makeAverager()
print(avg(10), avg(11), avg(12))

Let us check he values in __closure__.

for item in avg.__closure__:
    print(item.cell_contents) # 3 33

Reference

Fluent Python