Application of Closures in Python With Examples (When & Why)

This article explains different application of closure in Python along with when & why to use them.

Python Closure is basically a function with some free variables attached to it. This features of python can be used for different purpose. Here we list out different cases when Closures finds its application in Python.

1. Using Closure Instead of Class

In python, we can use closures instead of class in number of cases which reduces size of code lines & complexity. Here we present you an example implemented through both techniques, first by using class and then by using closures.

Consider implementing simple adder functionality which keeps adding number.

Class Implementation of Adder


class Adder:
    def __init__(self):
        self.total = 0
    
    def __call__(self,number):
        self.total += number
        return self.total

print('First Adder:')
s1 = Adder();
print(s1(10))
print(s1(50))
print(s1(100))

print('Second Adder:')
s2 = Adder();
print(s2(11))
print(s2(-88))
print(s2(111))
Output
First Adder:
10
60
160
Second Adder:
11
-77
34

Closure Implementation of Adder


def adder():
    total = 0
    def add(number):
        nonlocal total
        total += number
        return total
    return add


print('First Adder:')
s1 = adder();
print(s1(10))
print(s1(50))
print(s1(100))

print('Second Adder:')
s2 = adder();
print(s2(11))
print(s2(-88))
print(s2(111))
Output
First Adder:
10
60
160
Second Adder:
11
-77
34

2. As a Function Call Counter

Using closures, we can count number of times that certain function gets called easily. Here is an example for function call counter in Python.


def counter(func):
    count = 0
    def closure(*args, **kwargs):
        nonlocal count
        count += 1
        print("{0} has been called {1} times.".format(func.__name__, count))
        return func(*args, **kwargs)
    return closure

# Some other function
def add(a,b):
    print('Sum: ',a+b)

def sayHello():
    print("Hello")

# Testing
counter_add = counter(add)
counter_sayHello = counter(sayHello)

counter_add(2,3)
counter_add(6,7)
counter_sayHello()
counter_add(6,70)
counter_add(2,3)
counter_add(6,7)
counter_sayHello()
counter_add(6,70)
Output
add has been called 1 times.
Sum:  5
add has been called 2 times.
Sum:  13
sayHello has been called 1 times.
Hello
add has been called 3 times.
Sum:  76
add has been called 4 times.
Sum:  5
add has been called 5 times.
Sum:  13
sayHello has been called 2 times.
Hello
add has been called 6 times.
Sum:  76

3. Use of Closure in Decorators

Closures are widely used in decorators. In general, a decorator function takes a function as an argument and returns a closure. Decorators are generally used for extending the behavior of a function.

Here is simple decorators which adds dollar '$' sign before number and of course uses closure:


# Closure Application 3: Decorators

def decorator(fn):
    symbol = '$'
    def closure(*args, **kwargs):
        nonlocal symbol
        return symbol + str(fn(*args,**kwargs))
    return closure

@decorator
def add_symbol(number):
    return number

print(add_symbol(200))
print(add_symbol(3000))
print(add_symbol(80000))
Output
$200
$3000
$80000

Why To Use Closures? (Advantages)

In above-mentioned examples, we considered different cases for using closures. Here we list some important points about why we use decorators.

  1. One of the most important point for using Closures in Python is they provide some sort of data hiding as a callback functions. Which in turns reduce the use of global variables.
  2. In some cases using Closures instead of Class reduces code size.
  3. Closures are very suitable for replacing hard-coded constants.
  4. Closures are very useful in decorating function. Which we have already seen in aboove example.