This notebook contains an excerpt from the Python Programming and Numerical Methods - A Guide for Engineers and Scientists, the content is also available at Berkeley Python Numerical Methods.

The copyright of the book belongs to Elsevier. We also have this interactive book online for a better learning experience. The code is released under the MIT license. If you find this content useful, please consider supporting the work on Elsevier or Amazon!

# Nested functions¶

Once you have created and saved a new function, it behaves just like any other Python built-in function. You can call the function from anywhere in the notebook, and any other function can call on the function as well. A nested function is a function that is defined within another function - parent function. Only the parent function is able to call the nested function. However, the nested function retains a separate memory block from its parent function.

TRY IT! Consider the following function and nested function.

import numpy as np

def my_dist_xyz(x, y, z):
"""
x, y, z are 2D coordinates contained in a tuple
output:
d - list, where
d[0] is the distance between x and y
d[1] is the distance between x and z
d[2] is the distance between y and z
"""

def my_dist(x, y):
"""
subfunction for my_dist_xyz
Output is the distance between x and y,
computed using the distance formula
"""
out = np.sqrt((x[0]-y[0])**2+(x[1]-y[1])**2)
return out

d0 = my_dist(x, y)
d1 = my_dist(x, z)
d2 = my_dist(y, z)

return [d0, d1, d2]


Notice that the variables x and y appear in both my_dist_xyz and my_dist. This is permissible because a nested function has a separate memory block from its parent function. Nested functions are useful when a task must be performed many times within the function but not outside the function. In this way, nested functions help the parent function perform its task while hiding in the parent function.

TRY IT! Call the function my_dist_xyz for x = (0, 0), y = (0, 1), z = (1, 1). Try to call the nested function my_dist in the following cell.

d = my_dist_xyz((0, 0), (0, 1), (1, 1))
print(d)
d = my_dist((0, 0), (0, 1))

[1.0, 1.4142135623730951, 1.0]

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-2-1bec838581d7> in <module>
1 d = my_dist_xyz((0, 0), (0, 1), (1, 1))
2 print(d)
----> 3 d = my_dist((0, 0), (0, 1))

NameError: name 'my_dist' is not defined


Following is the code repeated without using nested function. Notice how much busier and cluttered the function looks and how much more difficult it is to understand what is going on. Also note that this version is much more prone to mistakes because you have three chances to mistype the distance formula. It is worth noting that this function could be written more compactly using vector operations. We leave this as an exercise.

import numpy as np

def my_dist_xyz(x, y, z):
"""
x, y, z are 2D coordinates contained in a tuple
output:
d - list, where
d[0] is the distance between x and y
d[1] is the distance between x and z
d[2] is the distance between y and z
"""

d0 = np.sqrt((x[0]-y[0])**2+(x[1]-y[1])**2)
d1 = np.sqrt((x[0]-z[0])**2+(x[1]-z[1])**2)
d2 = np.sqrt((y[0]-z[0])**2+(y[1]-z[1])**2)

return [d0, d1, d2]