In Python, the concept of closure is applicable only to Nested Functions. Closures in Python are the inner functions that have access to variables declared/initialized inside an outer function (enclosing function)even after the outer function has been executed completely or removed from the memory.
Before learning the working of python closures, let us understand the scope of variables in nested functions.
Whenever we print any variable inside an inner function, the Python interpreter searches for that variable declaration/initialization until four scopes. First, the local scope of the inner function, then the local scope of the enclosing function, then the global scope and at last the built-in module scope. So,the inner function can access the variables
declared/initialized in all these four scopes as shown in the below image.
Keeping this in mind, let us move ahead to understand Python Closures in detail.
Consider the below-given nested function in which the variable b is accessed inside the inner function.
def outer(): b = 20 #variable inside the outer functiondef inner(): c = 30 #variable inside the inner function print(b + c) inner() #call to inner() function #main() function outer() #call to outer() function
Here, since the inner function is called from the outer function, the Python interpreter starts the execution of the inner function before the outer function completes its execution. The above-defined function becomes closure when we return the inner function instead of calling it from the outer function. Let us see how to do that.
Let us consider the same example, where we rewrite the function definition by returning the inner function from the outer function instead of calling it as shown below.
def outer(): b = 20def inner(): c = 30 print(b + c) return inner #returning inner() function
Note:When returning the inner function, there is no need for round brackets after the function name.
Since we are returning the inner function from the outer function, we need to declare a variable in the main() function to accept and store the function returned from the outer() function as shown below.
#main() function result = outer() print(result) print(type(result))
So, when we execute the below code, we get the output as,
def outer(): b = 20def inner(): c = 30 print(b + c) return inner #returning inner() function #main() function result = outer() print(result) print(type(result))
Output: .inner at 0x7fadf75000d0> <class 'function'>
Here, the inner function returned from the outer function gets stored in the variable result. So, the variable 'result' has modified to a function and the same is evident in the result. Now, 'result' acts like a function, using which the inner function defined inside the outer function is called as shown below.
def outer(): b = 20def inner(): c = 30 print(b + c) return inner #returning inner() function #main() function result = outer() result()
It is assumed that a function completes its execution whenever it returns 0 or any values. Here in the above example, the outer() function returns the inner function. So, it has completed its execution. Once the outer function has completed its execution, we are calling the inner function from the main() function and still the inner() function is able to access the variable initialized inside the outer function. How is this happening?
Well!! When the Python interpreter detects the dependency of the inner function on the outer function, it stores the variables declared/initialized inside the outer function even if the outer function completes its execution (deleted from the memory).
A function that has this property of accessing a variable declared/initialized inside the outer function even after the outer function has deleted from the memory is called a Closure.
Python Closures are used when there is a need for data hiding. Also, they are used to bind the data to a function. For instance, in the above code, we have returned the inner function from the outer function and stored (bind) it to the variable result to call the inner function further. Similar to this we can bind any data to a function and use that function wherever required.
To conclude, a function should satisfy the following three criteria to become a closure. They are,