Before I talk about what Closure is and what it does? Let’s first understand scope resolution and nested function.
Whenever a python interpreter looks for the scope of a variable or function, it first searches in the Local namespace. If no match is found, it will look for it in the Enclosing scope, then Global scope and if still there is no match, it checks for it in the Built-in scope before raising the NameError exception.
A function inside another function is known as a nested function. Nested functions can only be accessed inside Outer functions. These nested functions can access variables defined inside an outer function. This property of being able to access variables leads to the concept of closure.
def Outer(var): def Inner(): print(var) Inner() Outer('message')
Since almost everything in Python is an object, therefore we can say that closure is an inner function object. More specifically, closure is a function object capable of remembering the environment in which it was created. This helps closure to access variables even after the outer function has finished its execution or even if we explicitly delete the Outer function. It also helps in extending the scope of the inner function. We can say that closure is a function that has variables bound to it immutably(data cannot be changed using closure). While returning the inner function, unlike the nested function we don’t use (Parenthesis) in closure.
def Outer(inp): def Inner(): print(inp) return Inner output = Outer('Calling inner function') print(output.__closure__.cell_contents) output.__closure__ = 'Calling outer function'
Calling inner function
TypeError: ‘tuple’ object does not support item assignment
Now if we explicitly delete the Outer function. We will still be able to access the inner function.
def Outer(inp): def Inner(): print(inp) return Inner a = Outer('Calling inner function') del Outer print(Outer('Can we access Outer after deleting')) a()
NameError: name ‘Outer’ is not defined
Since we have deleted the Outer function, now if we try to access the inner function we can access it as closure remembers the environment in which it was created.
def Outer(inp): def Inner(): print(inp) return Inner a = Outer('Calling inner function') del Outer a()
Output: Calling inner function
Closure with parameter
We can also pass parameters inside an inner function using a closure.
def multiplyFirst(x): def multiplySecond(y): return x*y return multiplySecond multi = multiplyFirst(5) print(multi(5))
Criteria for Closure
- There must be a nested function.
- The nested function refers to the value defined in the enclosing function.
- The outer Function must return the inner function.
When to use Closure
- Closure can be used as a replacement for a class. Consider when you have only one method inside a class. You can use closure to avoid unnecessary instantiation of objects and instance variables. It also helps in improving the readability of code.
- Closure can be used with a decorator.
- The closure is also helpful in reducing the unnecessary usage of global variables.
- Closures are somewhat like a callback function; you cannot access them directly. It helps in data hiding. Suppose your outer function serves the functionality of the submit button, you can implement some functionalities inside the closure which will basically make sure what should happen after some click on the submit button.
Special thanks to Arya Singh for contributing to this article on takeUforward. If you also wish to share your knowledge with the takeUforward fam, please check out this article. If you want to suggest any improvement/correction in this article please mail us at [email protected]