liveBook · Manning

Closure

As explained in Python How-To

A closure is a function that retains access to variables from its enclosing lexical scope after that scope has finished executing.

How can a decorator still call the function it was given after the decorator has returned? It returns an inner function that retains access to that function. This inner function is a closure: it uses a variable from its enclosing function’s scope, even after that outer call has finished. section 7.3.2

A decorator that creates a closure

def monitor(func): def monitored(): print(f"*** {func.__name__} is called") func() return monitored @monitor def example(): pass example() # *** example is called Calling monitor creates and returns monitored. When example() runs, that returned function can still access func, the original example function. section 7.3.2

A wrapper that accepts no arguments fails when the decorated function needs one. For a reusable decorator, let the inner function accept *args and **kwargs, pass them to the original function, and return its result. Use functools.wraps(func) on the inner function to preserve the original function’s __name__ and __doc__; otherwise, those attributes describe the wrapper instead. section 7.3.2 section 7.3.3

>>> closure.__closure__[0].cell_contents
100
>>> closure.__closure__[1].cell_contents
5

Inspecting __closure__ shows the values bound by an inner function created through outer(100): 100 and 5. This is a useful check of what that particular closure retains, not a step required to use decorators. section 7.3.2

How Python How-To covers it

How deep it goes
Identifies the outer function, returned inner function, and bound variables, but defers a full explanation of scopes and nonlocal binding.
Examples
Uses a returned function called after outer(100), a monitoring decorator, and docstring and name checks on decorated functions.
What it assumes
Assumes familiarity with functions and higher-order functions while introducing closure structure without requiring a full account of scopes.
What you can do after
Build it from scratch as a decorator wrapper that forwards arguments and results while preserving metadata with functools.wraps.
How it connects
Links closures to higher-order functions, decorators, nonlocal variable binding, and function metadata.

Also explained in

Compare how 20 books explain closure →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Python How-To. The section links point to the parts of the book it draws on.