Topics

Python Closures

Welcome to a tutorial on Closure in Python. 

Before we proceed with Closure, let’s understand what nested functions as well as non-local variables.

 

Nested functions and Non-local variables

Nesting of function refers to a scenario where a function is defined inside another function; and when the function inside which another function is defined is called the outer function; and also, the function which is defined inside another function is called the inner function. Check out the example below:

#defining nested function
def outer(message):
    #text is having the scope of outer function
    text = message
    def inner():
        #using non-local variable text
        print(text)
    #calling inner function
    inner() 

# main method
if __name__=='__main__':
    outer('Hello!')

Output:

Hello!

From the above example, the function inner() can access the local variable text of the outer function outer() which has a scope that extends up to the whole body of the outer() function.

The local variable text of the outer function is referred to as a non-local variable for the inner function which it can access, but cannot modify.

 

Concept of Closures

A closure is a function object, that is, a function that behaves like an object, that remembers values in enclosing scopes even if they are not present in memory. If a function is available inside another function, then closure is created, as the inner function will have access to variables and parameters of the outer function even after the outer function is returned. In this regard, the inner function can be called later and it will have access to variables and parameters of the outer function. '

Precisely, the closure has reference to the variables and parameters of the outer function. So, it can be said that closure is a record that stores a function together with an environment.

#defining nested function
def outer(message):
    #text is having the scope of outer function
    text = message
    def inner():
        #using non-local variable text
        print(text)
    #return inner function
    return inner 

# main method
if __name__=='__main__':
    func = outer('Hello!')
    func()

Output:

Hello!

 

You can see that we used the closure in the example above, to access the inner() function out of its scopes since the inner() function is only available inside the outer() function but by returning it, we can access it outside the outer function as well. So, therefore, in the main method, we called the outer() function and returned the inner() function refers to the func variable.

Thus, you notice that the func variable has reference to the inner() function, meaning that we use parentheses with the func variable and it will work as an inner() function which is accessing the text variable of the outer() function that was called at the time of the func variable declaration.

def inrementor(m):
    # inner function operation
    def operation(n):
        # n is incremented by m
        return n + m
    # return the inner function
    return operation
 
incrementby1 = inrementor(1)
incrementby5 = inrementor(5)
incrementby9 = inrementor(9)
 
# should print 2
print(incrementby1(1)) 
# should print 6
print(incrementby5(1))
# should print 10
print(incrementby9(1))

Output:

2
6
10

The example in this section is quite complex. This is because we will use the arguments in the inner operation(n) function. Therefore, if the incrementor(m) function is called, it returns the reference to the operation(n) function.

Also, as we are defining the variables incrementby1, incrementby5 and incrementby9, we passed the value of the m argument every time.

 

Important Points on Closures

Note the points, as they are necessary for implementing closures in Python:

  • There should be a nested function, that is, a function inside a function.
  • Then, the inner function must refer to a non-local variable or the local variable of the outer function.
  • And the outer function must return to the inner function.

 

When do you use Closures?

The answer to this question is highlighted below:

  • The use of Closures can avoid the use of global values.
  • It provides some form of data hiding when needed.
  • And, if cases where few methods (i.e. one method in most cases) are to be implemented in a class, closures can provide a better solution. However, if the number of attributes and methods is more, it is better to implement a class