What is closure in Python?
A Closure is a function object that remembers values in enclosing scopes regardless of whether they are absent in memory. Let us get to it bit by bit
Nonlocal variable in a nested function
Firstly, a Nested Function is a function characterized inside another function. It’s important to take note that the nested functions can get access to the variables of the enclosing scope. Although, in python, they are just read-only. However, one can utilize the “nonlocal” keyword explicitly with these variables so as to adjust them.
def transmit_to_space(message): "This is the enclosing function" def data_transmitter(): "The nested function" print(message) data_transmitter() print(transmit_to_space("Test message")) #output #Test message #None
Defining a Closure function
In the example above, what might occur if the last line of the function transmit_to_space() restored the data_transmitter() function instead of calling it? This implies the function was characterized as follows:
def transmit_to_space(message): def data_transmitter(): print(message) return data_transmitter another = transmit_to_space("Hello") another() #output #Hello
The transmit_to_space() function was called with the string “Hello” and the returned was bound to the name another. On calling another(), the message was still recollected in spite of the fact that we had just wrapped up the transmit_to_space() work.
This procedure by which a few data (“Hello” for this situation) gets appended to the code is called closure in Python.
This value in the enclosing scope is remembered in any event when the variable goes out of scope or the function itself is removed from the current namespace.
Try running the accompanying in the Python shell to see the output
del transmit_to_space another() #Hello transmit_to_space("Hello") #NameError: name 'transmit_to_space' is not defined
Python closure with a non local keyword
This works well as the ‘data_transmitter’ function can access the ‘message’. To demonstrate the use of the “nonlocal” keyword, consider this
def print_msg(number): def printer(): "Here we are using the nonlocal keyword" nonlocal number number=3 print(number) printer() print(number) print_msg(9) #output #3 #3
Python closures vs. classes
Python closures can be an alternate solution to small classes.
class Classes(): def __init__(self): self.data =  def __call__(self, val): self.data.append(val) _sum = sum(self.data) return _sum cls = Classes() s = cls(1) print(s) s = cls(2) print(s) s = cls(3) print(s) s = cls(4) print(s) #output #1 #3 #6 #10
We have a Classes class, which sums values passed to the object.
def __init__(self): self.data = 
The data is kept in the object attribute and is created in the constructor.
def __call__(self, val): self.data.append(val) _sum = sum(self.data) return _sum
Each time the instance is called, the value is appended and the sum is calculated and returned.
The following is an alternate solution with Python closure.
def make_sum(): data =  def summer(val): data.append(val) _sum = sum(data) return _sum return summer summer = make_sum() s = summer(1) print(s) s = summer(2) print(s) s = summer(3) print(s) s = summer(4) print(s) #output #1 #3 #6 #10
The same functionality with Python closure:
def make_sum(): data =  def summer(val): data.append(val) _sum = sum(data) return _sum return summer
Because the data is a list which is mutable, we do not have to use the nonlocal keyword.
When and why use closure?
- As closures are utilized as callback functions, they provide the sort of data hiding. This encourages us to reduce the utilization of global variables.
- At the point when we have scarcely any functions in our code, closure proves to be productive way. Although it may, need to have numerous function, then go for class (OOP).
- It is a record that stores a function along with a situation: a mapping associates each free variable of the function (variables that are utilized locally, however, characterized in an enclosing scope) with the value or reference to which the name was bound when the closure was made.
- A closure—in contrast to a plain function—permits the function to access those captured variables through the closure’s duplicates of their values or references, when the function is summoned outside their scope.