Python Closure: How and Why to use

Python Closure: How and Why to use

7 mins read1.2K Views Comment
Updated on Aug 27, 2024 17:44 IST

Closure in python is the function that remembers values in enclosing scopes even if they are not present in memory. In this article, we will discuss about python closure in detail with the help of examples.

2022_08_Python-Closure.jpg

In this article, we will be looking into the concept of python closures in detail. But to understand the concept of closures in Python we need to make ourselves familiar with the concept of Nested Functions.

Let’s get started with the Nested Function first.

Nested Functions in Python:

Whenever we define a function inside another function is called a nested function.  

For instance, take a look at the below examples.

Example 1:


 
# enclosing outer
# function definition
def outer_function(test_string):
# inner function definition
def inner_function():
print(test_string)
# calling inner_function()
# within the outer_fun()
# ie,nested function
return inner_function()
# calling the outer_function()
outer_function("Naukri")
Copy code

Output:

Naukri

In the above example, we have defined a function called the outer_function(), which is the outer function within which the inner function namely, inner_function() is defined. Then we made a call for the inner function inside the scope of the outer function. Finally, we made a call to the outer function(ie, outer_function()), outside the scope of the outer function. The outer_function() takes a test_string as a paramere and the inner_function() just simply prints the parameter received by the outer_function(). In other words, we can say that the outer_function() is an enclosing function and the inner_function() a local function of the enclosing function.

As we can observe from the output, the outer_function() receives a test_string(ie, Naukri), and the inner function simply prints the test string received by the outer function as a parameter.

Must Read: What is Python?

Must check: Python Online Course and Certification

Let’s take one more example to better understand the concept of Nested Functions.

Example 2:


 
# function to pop last element
# from a given list
# outer/enclosing function
def pop(list):
# inner function
def get_last_item(my_list):
# returns last element
# from list received by the
# outer function
return my_list[len(list)-1]
# remove the last element
# from list
list.remove(get_last_item(list))
# return list
return list
# test_list
test_list = [1,2,3,4,5]
# pop 5 from list
print(pop(test_list))
# pop 4 from list
print(pop(test_list))
# pop 3 from list
print(pop(test_list))
# pop 2 from list
print(pop(test_list))
Copy code

Output:

[1, 2, 3, 4]
[1, 2, 3]
[1, 2]
[1]

We have defined this pop() function which is our outer/enclosing function and then we have defined a function called get_last_item() which is our inner/local function to the pop function. Now, this pop() function takes the list as an argument.  In the get_last_item() function, whenever you pass a list as an argument to this local function, it’s going to find out the last element of the list and return the last value of this list. 

Now you may already know that you can call a function called () on your lists which is used to remove some items from the list. So we are just calling the remove() function on the list and as an argument of the list, we are passing the function which finds out the last element of the list. So the inner function is going to give us the last element of the list and then the last element will be removed from the list using the remove() function. Finally, we are simply returning the list which is passed as an argument to the pop function after removing the last element.

As you can observe in the output of the above function call that when the first pop is called it’s going to remove the last element which is 5 from the list and then whenever the second pop is called it’s going to remove the four and whenever the third pop method is called it’s going to remove the three and so on and so forth.  This is how you can use nested functions in Python.

Must Read: Why use Python Datetime module?

Must Read: Free QR generator using Python

Now let’s talk about the closures in Python.

Recommended online courses

Best-suited Python courses for you

Learn Python with these high-rated online courses

Free
6 weeks
– / –
2 weeks
– / –
16 weeks
1.7 K
3 months
– / –
– / –
4.24 K
2 weeks
3 K
3 weeks
– / –
4 months

Python Closures:

For the sake of simplicity while understanding the concept of closures, let’s bring back the example we used as example 1. So the below function as we know is a nested function. 


 
# enclosing outer
# function definition
def outer_function(test_string):
# inner function definition
def inner_function():
print(test_string)
# calling inner_function()
# within the outer_fun()
# without parentheses
return inner_function
# calling the outer_function()
outer_function("Naukri")
Copy code

Output:

No Output

Now in order to convert this nested function into a closure, we need to return the inner function without the parentheses(ie, return inner_function() to return inner_function).  So the thing to note here is we don’t need to return the inner_function() with the parentheses. This is the simplest example of closure. 

A closure is a function whose return value depends on the value of one or more variables that are declared outside the function. So in the above example, this test_string variable is declared outside the inner function and the value of this inner function depends on that variable. This makes it a closure.

Must Read: Pattern Program in Python

Must Read: Type Conversion in Python

The closure has a special property that the closure function object remembers the value in the enclosing scope even if they are not present in the memory. 

So to use this outer function which now uses closure,  we need to treat the outer function as a Python object. And that object holds the inner function within it. for this we need to declare a variable x as shown below:


 
x = outer_function("Naukri")
Copy code

At this point our example code looks like the below:


 
# enclosing outer
# function definition
def outer_function(test_string):
# inner function definition
def inner_function():
print(test_string)
# calling inner_function()
# within the outer_fun()
# without parentheses
return inner_function
# treat the outer_function() as object
x = outer_function("Naukri")
# call function object
x()
Copy code

Output:

Naukri

So in order to use this x as the function, we can just call the x using the parentheses because this function doesn’t take any arguments.  We are not passing any argument inside x, but we will just call it as a function because this outer function is just returning the inner function.

As we discussed above, a closure is a function object that remembers the value in the enclosing scope even if they are not present in the memory. So our enclosing scope is the outer function, therefore even if we delete the outer function after declaring the statement and if the x variable contains the inner function then and at this point, the system will still work for x.

Must Read: Comparison Operator in Python

Must Read: Memory Management in Python

For example, let’s  just delete the outer function using the del keyword and call the outer function again as shown below:

Example 1:


 
# enclosing outer
# function definition
def outer_function(test_string):
# inner function definition
def inner_function():
print(test_string)
# calling inner_function()
# within the outer_fun()
# without parentheses
return inner_function
# treat the outer_function() as object
x = outer_function("Naukri")
# delete the outer function
del outer_function
outer_function("Naukri")
# call function object
x()
Copy code

Output:

2022_08_image-65.jpg

As we can see in the above output that the program throws us an error stating that the function (ie, outer_function()) does not exist. 

Now comes the interesting part, if we now just make a call to x(), it will return us a valid output even if the outer_function() gets deleted. Take a look at the below program for reference:


 
# enclosing outer
# function definition
def outer_function(test_string):
# inner function definition
def inner_function():
print(test_string)
# calling inner_function()
# within the outer_fun()
# without parentheses
return inner_function
# treat the outer_function() as object
x = outer_function("Naukri")
# delete the outer function
del outer_function
# call function object
x()
Copy code

Output:

Naukri

The above code works because we have already stored the value of the inner function in the variable x before deleting the outer_function(). This is the magic of closures in python.

A closure function is able to remember the values which are declared outside the function. Now let’s take one more example of the closure so we will be able to understand it in a better way.

Example 2:


 
# enclosing outer
# function definition
def nth_power(exponent):
# inner function definition
def pow_of(base):
return pow(base,exponent)
return pow_of
Copy code

In the above example, we have defined a function called nth_power() and we pass one argument in it, which is an exponent.  Inside this nth_power() function, we have defined a local function that also takes one argument(ie, base) and then it returns the power of whatever argument we pass to the pow_of() function, and the value of the exponent is coming from the outer scope, ie, this parameter is passed to the outer function(ie, nth_power()). Finally, we are returning the pow_of function without any parenthesis.

Now let’s declare a variable called square, that contains the value of the nth_power function. We will pass 3(ie, the exponent) as an argument to the nth_power() function. Then we will just print the value the square function and pass 5(ie, base) as an argument to it. The code would look like the below:


 
# enclosing outer
# function definition
def nth_power(exponent):
# inner function definition
def pow_of(base):
return pow(base,exponent)
# calling inner function
# within the outer function
# without parentheses
return pow_of
# treat the outer function as object
square = nth_power(3)
# calling the function object
print(square(5))
Copy code

Output:

125

As we can see in the output, we used the square function object to find the 3rd exponent of base 5, meaning 5^3 = 5*5*5= 125. So it gave us the cube of 5. The square variable is holding the status of the inner function. This phenomenon can be observed in Python classes. The classes are able to remember the state of the variables and the methods which are declared inside the classes.

Must Read: Python if-else statement

Must Read: Abstraction in Python

Conclusion:

So closures are sometimes used in place of the classes which usually have only one method inside them.  So closures can be used in place of the classes which have fewer methods generally one method inside them. The closure can have the following advantages:

  • We can avoid the use of global values  by calling the local function outside its scope, and accessing the enclosed variable outside its scope.
  • It is great for hiding data in your programs and is highly used while building python microservices.
  • It is used for implementing decorators in Python.
About the Author

This is a collection of insightful articles from domain experts in the fields of Cloud Computing, DevOps, AWS, Data Science, Machine Learning, AI, and Natural Language Processing. The range of topics caters to upski... Read Full Bio