Before learning about what a closure is, we have to first understand what are nested functions and non-local variables.
Nested functions in Python
A function which is defined inside another function will be a nested function. Nested functions can to access variables of the enclosing scope.
In Python, these non-local variables can be accessed only within their scopebut not outside their scope. This can be illustrated by following example:
# Python program to illustrate
# nested functions
def outerFunction(text):
text = text
def innerFunction():
print(text)
innerFunction()
if __name__ == '__main__':
outerFunction('Hey!')
As we can see here innerFunction() can easily be accessed inside the outerFunction body but not outside of it’s body. Hence, here, innerFunction() is treated as a nested Function which uses text as it's non-local variable.
# Python program to illustrate
# closures
def outerFunction(text):
text = text
def innerFunction():
print(text)
return innerFunction # Note we are returning function WITHOUT parenthesis
if __name__ == '__main__':
myFunction = outerFunction('Hey!')
myFunction()
Output:
Hey!
As observed from the code given above, closures help to invoke function outside their scope.
# Python program to illustrate
# closures
import logging
logging.basicConfig(filename='example.log', level=logging.INFO)
def logger(func):
def log_func(*args):
logging.info(
'Running "{}" with arguments {}'.format(func.__name__, args))
print(func(*args))
# Necessary for closure to work (will return WITHOUT parenthesis)
return log_func
def add(x, y):
return x+y
def sub(x, y):
return x-y
add_logger = logger(add)
sub_logger = logger(sub)
add_logger(3, 4)
add_logger(4, 5)
sub_logger(10, 4)
sub_logger(20, 10)
Output
7
9
6
10
When and why to use Closures: