text: We can do a lot with functions like passing a function as an argument to another function, calling a function from another function, etc. In Python, we can also create a function inside another function.
  A function which is created inside another function is called a nested function or an inner function. In this chapter, we will read about nested functions and their significance.
  Defining a Nested Function
  A nested function is defined by simply creating it using the def keyword inside another function.
  Here is an example.
  def outer(): # outer function print("This is outer function") def inner(): print("This is inner function") inner() # calling inner function outer() # calling outer function
  We defined a function named
  inner() inside another function named
  outer(). Thus,
  inner() is a nested function.
  When the
  outer() function is called, its body is executed. Inside its body, the
  inner() function is defined and then called. Thus, we first called the
  outer() function which in turn called the
  inner() function.
  Note that an inner function is always called from inside the function in which it is defined. Thus, to call the inner function, we need to call the outer function.
  A nested function can access the variables defined in the function in which it is created. This is demonstrated in the following example.
  def outer(): # outer function x = 10 def inner(): print("Inside inner func", x) inner() # calling inner function print("Inside outer func", x) outer() # calling outer function
  In this example, we defined a variable x having a value of 10 in the
  outer() function. When we printed the value of x in the nested function, it got printed. This means that the nested function can access the variable x defined in its parent function.
  So, from the above examples you must have understood that nested functions are just normal functions which are defined and called inside some other function.
  Let’s see one more example.
  def find_power(num): # outer function def power(n): return num ** n return power(2) # calling inner function and returning the value returned by it print(find_power(10)) # calling outer function
  This was a straight forward example. The
  find_power() function is called by passing 10 as argument, making its parameter num equal to 10. Inside the
  find_power() function, the nested function
  power() is called by passing 2 as argument, making the parameter n of the
  power() function equal to 2. Inside the
  power() function,
  num (10) raised to the power n (2) is returned. Finally, this value returned by the
  power() function is returned by the
  find_power() function.
  Significance of Nested Functions
  There can be many reasons to use nested functions. Let’s see some of them.
  Nested functions can serve as helper functions of the function in which they are defined. Let’s see an example in which a nested function serves as a helper function for its parent function.
  def print_even(lst): def find_even(num): if num % 2 == 0: return True else: return False new_list = [] for num in lst: if find_even(num) == True: new_list.append(num) print("Final list:", new_list) mylist = [1, 2, 4, 5, 6, 7, 10, 11, 12] print_even(mylist)
  Here the function
  print_even() receives a list as the argument and prints a new list containing all the even elements of the list received. You must have understood the rest of the program.
  Inside the
  print_even() function, we have a nested function
  find_even() which receives a number as the argument and returns True if the passed number is even, else returns False. In this program, the nested function thus works as a helper function which just checks if the passed number is even and is not affected by any other code or variable inside the outer
  print_even() function.
  Another use case of nested functions can be seen from the following example.
  def get_factorial(num): def factorial(num): if num == 0 or num == 1: return 1 else: return num * factorial(num - 1) if not isinstance(num, int): raise TypeError("Failed! The value must be a number") if num < 0: raise ValueError("Failed! The number must be non-negative") return factorial(num) print(get_factorial(5))
  In the above example, the
  get_factorial() function takes a number as argument and returns the factorial of that number. Inside the
  get_factorial() function, we are doing some error handling, in which we are raising the TypeError exception if the passed number is not an integer and the
  ValueError exception is the passed number is less than 0 (You can learn about raising exceptions from this chapter). If no exception is thrown in both the checks, then the nested function named
  factorial() is called which returns the factorial of the number.
  Now suppose if the code for both error handling and factorial calculation was written in the
  get_factorial() function without using the nested function
  factorial(), the complexity of the code inside
  get_factorial() would have increased.
  So by now, you must have got an idea of when you can use nested functions to reduce the complexity of your functions. Let’s look at some more cases when nested functions can be used.
  Sometimes we might want to prevent some function from being directly accessed from anywhere in your program. In that case, we can put that function (say
  f2()) as a nested function inside another function (say
  f1()). We know that a nested function can’t be accessed outside the function in which it is defined, and hence we won’t be able to access that function from other parts of the program anymore. In order to call the nested function f2(), we first will have to call its parent function
  f1() which will call
  f2() inside it. This hiding of some data or code (function in our case) is known as encapsulation.
  But why would we encapsulate a function?
  To answer that, let’s take a use case where we want to predict if a company will get profit or loss. Suppose we have a function which contains a logic that calculates the expected profit of a company. This logic might contain some information which we don’t want anyone to know. If we don’t want any other part of the program to directly access the logic in this function, we can put it as a nested function inside another function. Look at the following function structure.
  def profit_or_loss(): def get_profit(): # calculates profit return profit if profit > 0: return "Profit" else: return "Loss" profit_or_loss()
  Suppose
  get_profit() is the nested function with the logic that calculates and returns the expected profit, and
  profit_or_loss() is the function inside which it is encapsulated. Now, if the user wants to know if there will be profit or loss, then he/she will call the
  profit_or_loss() function. This function will call the
  get_profit() function to get the profit, and will return “Success” if the profit is positive, else returns “Loss”. In this way, no other part of the program is able to access the nested
  get_profit() function.
  Nested functions are also used for creating closures. We will read about closures in Closures.
  Now that you understand what nested functions are and where to use them, start including them in your programs wherever necessary.