Closures In Python

Pavol Kutaj
3 min readMar 14, 2022

The aim of this page📝is to conceptualize closures and nested scopes, pointing out that there are 2 confusingly unrelated meanings of closures: 1) used in computer science 2) used in math/set theory. This note is about the first meaning encountered in Python. I’ll end with some notes on the 2).

1. REPETITION/FOUNDATION

  • local functions in Python can reference bindings in enclosing scopes
  • local functions can be returned as objects and executed in different scopes
  • question: how does a returned local function retain access to its enclosing — yet no longer existing — scope?
  • again, once a local function is returned from its enclosing scope, that enclosing scope is gone along with any objects it defined in its scope
  • How can the local function operate without that enclosing scope

2. CLOSURE

  • answer: local functions forms something that is known as a closure
  • closure persists those objects from enclosing scopes that the local function needs
  • it keeps these selected objects “alive” so that when the local function is executed, they can still be used
  • terminologically, the local function closes over the objects it needs
  • …preventing them from being garbage collected
  • python implements closed with special attribute __closure__
  • if a function closes over any object, that function has a `closure attribute
  • the attribute maintains the necessary references to those objects
# >>> lf.__closure__
# (<cell at 0x02201A78: str object at 0x01F64D90>,
  • the closure above is referring to a single object
  • the object is the x variable defined in the function that defined it

3. USAGE: FUNCTION FACTORIES

  • the fact that local functions can safely use objects from their enclosing scopes when bound to names can be useful
  • the typical use-case is a function factory: functions that return other functions
  • the return functions are specialized in some way based on the arguments passed to the factory
  1. factory function takes in some arguments
  2. factory functions creates a local function
  3. local function takes in its arguments
  4. local function uses arguments passed to the factory
  5. the combination of runtime function definition and closures makes this possible

3.1. EXAMPLE: RAISE NUMBER TO A POWER

  • you want to call a function to get a function
  • you use that specialized returned function
  • raise_to_exp(x) is a local function
  • raise_to_exp(x) refers to exp which is defined in an enclosing scope
  • once raise_to_exp(x) is called, Python will create a closure that refers an object created by calling raise_to(exp)
  • … so that the value of exp persisted once bound to a variable

SICP, MATH AND CLOSURE CONFUSION

  • For anyone ever touching Structure and Interpretation of Computer Programs: there are 2 unrelated meanings of closure (CS VS Math), see Wikipedia for the latter/less common one:

Sussman and Abelson also use the term closure in the 1980s with a second, unrelated meaning: the property of an operator that adds data to a data structure to also be able to add nested data structures. This usage of the term comes from the mathematics usage rather than the prior usage in computer science. The authors consider this overlap in terminology to be “unfortunate.”

Our ability to use tuples as the elements of other tuples provides a new means of combination in our programming language. We call the ability for tuples to nest in this way a closure property of the tuple data type. In general, a method for combining data values satisfies the closure property if the result of the combination can itself be combined using the same method.

--

--

Pavol Kutaj

Today I Learnt | Infrastructure Support Engineer at snowplow.io with a passion for cloud infrastructure/terraform/python/docs. More at https://pavol.kutaj.com