When (and why) should we use closures in python instead of classes?

Anuj Subedi
3 min readSep 18, 2019

--

Inroduction to closure:

The most simple way to think of a closure is a function that can be stored as a variable (referred to as a “first-class function”), that has a special ability to access other variables local to the scope it was created in.

Before we dive into closure we look in two fundamental aspects. They are:

  1. Nested Function on python
  2. Non local variables in python
  1. Nested Function on python

As similar to nested for and nested if; nested function is also a function having another function inside it.

def outer():
msg = "I am outer function"
def inner():
msg = "I am inner function"
print(msg)
inner()
print(msg)
outer()

Output:

I am inner function
I am outer function

2. Non local variable in python

def outer():
msg = "I am outer function"
def inner():
nonlocal msg #we have used nonlocal keyword here
msg = "I am inner function"
print(msg)
inner()
print(msg)
outer()

Output:

I am inner function
I am inner function

Here nonlocal keyword change the scope of variable msg. In previous example inner function did not changed the value of outer function’s msg value. But in this example we can see that inner function changed the msg variable of embedded (outer) function.

How to define a closure?

  1. define a nested function (function inside a another function)
  2. Parent (enslosed) function must return nested (inner) function

Note that the retured nested function should not be called in return statement. It should simply return a function (look at solution section below).

Problem

Assume that you have a class which define single method inside it (__init__ is not counted here). But you want to simplify your code. For this you would much just have a simple function which work like a class method.

import requests
class SourceTemplate:
def __init__(self, url):
self.url = url
def load(self, **kwargs):
return requests.get(self.url.format_map(kwargs))
github = SourceTemplate('https://api.github.com/repositories?since={since}')
github.load(since=200).json()

Why we use class here?

In many cases, the only reason we might have a single-method class is to store additional state for the use in method. In above example, the only purpose of using SourceTemplate class is to hold the url value some palce so that it can be used in load method.

Problem Alert: Is it good to use class to just store additional state like above example?. No, definetly not. So then what’s the solution?

Solution

Let’s use closure to solve it. In this above class, we can see single method inside it (bisides __init__). For such class, it can be turned into a functions using closures. Consider as an example, the following class, which allows us to fetch URL using a kind of template scheme.

The above class can be replaced with simpler function:

def sourcetemplete(url):
def load(**kwargs):
return requests.get(url.format_map(kwargs))
return load
load = sourcetemplete('https://api.github.com/repositories?since={since}')
load(since=200).json()

Why we used inner function or closure as a solution?

It is often more elegant to use closure insted of class. Simply stated, a closure is just a function, but with an extra enviroment of the variables they are used inside inner function.

As stated at defination section of closure in this post; “a key feature of a closure is that it remembers the enviroment in which it was defined”. This is the reason how function remembers the value of the url argument, uses it in subsequent calls.

When should we use closure?

Whenever we write code in python (which is also popular in javaScript) and encounter the problem of attaching additional state of function (such as above), it is a time to think about closure.

Why to should we use closure?

i. to replace hard coded constants.

ii. to reduce the use of global variables

iii. Since it wrok as callback function, it provides some sorts of data hiding

iv. provide an object oriented solution to the problem

When and Why it is better to use closure instead of class?

From the above problem and solution, we can conclude that we can use closure instead of class when:

i. we need stores/remembers the enviroment

ii. class contains single method besides __init__ method.

The reason why it is better to use closure instead of class (where applicable) is that they are often a more minimal and elegant solution than the alternative of turning your function into full-fledged class.

Happy coding !

--

--