Python Closures: Nonlocal Variable in A Nested Function
Python Closures: Nonlocal Variable in A Nested Function
In this tutorial, you'll learn about Python closure, how to define a closure, and
the reasons you should use it.
def print_msg(msg):
# This is the outer enclosing function
def printer():
# This is the nested function
print(msg)
printer()
Output
Hello
We can see that the nested printer() function was able to access the non-
local msg variable of the enclosing function.
def printer():
# This is the nested function
print(msg)
Output
Hello
That's unusual.
The print_msg() function was called with the string "Hello" and the returned
function was bound to the name another . On calling another() , the message
was still remembered although we had already finished executing
the print_msg() function.
This technique by which some data ( "Hello in this case) gets attached to the
code is called closure in Python.
This value in the enclosing scope is remembered even when the variable
goes out of scope or the function itself is removed from the current
namespace.
Try running the following in the Python shell to see the output.
Here, the returned function still works even when the original function was
deleted.
The criteria that must be met to create closure in Python are summarized in
the following points.
Closures can avoid the use of global values and provides some form of data
hiding. It can also provide an object oriented solution to the problem.
When there are few methods (one method in most cases) to be implemented
in a class, closures can provide an alternate and more elegant solution. But
when the number of attributes and methods get larger, it's better to implement
a class.
def make_multiplier_of(n):
def multiplier(x):
return x * n
return multiplier
# Multiplier of 3
times3 = make_multiplier_of(3)
# Multiplier of 5
times5 = make_multiplier_of(5)
# Output: 27
print(times3(9))
# Output: 15
print(times5(3))
# Output: 30
print(times5(times3(2)))
Run Code
Output
27
15
30
All function objects have a __closure__ attribute that returns a tuple of cell
objects if it is a closure function. Referring to the example above, we
know times3 and times5 are closure functions.
>>> make_multiplier_of.__closure__
>>> times3.__closure__
(<cell at 0x0000000002D155B8: int object at 0x000000001E39B6E0>,)
The cell object has the attribute cell_contents which stores the closed value.
>>> times3.__closure__[0].cell_contents
3
>>> times5.__closure__[0].cell_contents
5