Nested methods in python

What is a nested method
If a method is defined inside another method, the inner method is said to be nested inside the outer method or it is called Nested method.
All languages do not support nesting a method inside another method but python allows you to do so.

Benefit
Suppose there are some lines of code inside a function(or method) which are repeating multiple times. Instead of repeating them, you can put them inside a separate method and call that method where those lines are required. This prevents repeating lines of code as they are encapsulated in a single method which is called where those lines are required as shown below.

def method():
   # some code
   # execute repeating code
   method_repeated()
   method_repeated()
   method_repeated()
   method_repeated()

def method_repeated():
   // some code
   // some code

Above approach is good for preventing code repetition but there are following 2 concerns with this.

  1. Sometimes the repeating code lines are specific to the same method and it does not make a sense to group them into a separate external method since they are not required anywhere else.
  2. Code grouped into a separate method might require access to some variables or values from its caller method. This shall require passing those values are arguments to the separate method.

Both the above concerns are resolved if instead of moving repeated code into an external method, it is written inside the same method which requires it.

Creating nested methods
Nested methods are created the same way as normal methods are made. The only difference is that they are written inside another method. An example will make it more clear

def outer_method(numone, numtwo):
        # nested method
        def operations(innerone, innertwo):
            print("Sum of numbers", innerone + innertwo)
            print("Product of numbers", innerone * innertwo)
        # call nested method
        operations(numone, numtwo)
        

# call outer method
outer_method(10, 20)

Above example defines a method which contains another method. Nested method accepts two arguments and performs addition and multiplication of those arguments and prints the result.
Remember that in order for nested method to execute, you need to call it from inside the outer method. You can call it as many times as you want from inside the outer method.
Note that nested method can be called from inside outer method only. This is because the scope of nested(or inner) method is limited to the body of outer method only and it is not visible from outside.
Trying to call inner method directly from outside will raise an error

NameError: name ‘operations’ is not defined

Also, inner method can access the variables defined in the outer method as shown below.

def outer_method(numone, numtwo):
        # variable defined in outer method 
        outer_var = 30
        # inner method
        def operations(innerone, innertwo):
            # access outer method variable
            print("Value of outer method variable is", outer_var)
        # call inner method
        operations(numone, numtwo)

# call outer method
outer_method(10, 20)

Value of outer method variable is 30

As shown above, inner method can access the variables of outer method but vice-versa is not true. Outer method does not have access to the variables declared in the inner method.
This makes sense as the inner method is a block inside the outer method. An inner block can always access the attributes of outer block but the attributes inside inner block are local to that block only.

Inner methods in class
Creating inner methods in a class is also same as creating nested methods outside the class. When passing arguments to the outer method, you need to pass self as the first argument but that is something not related to nested methods.
Example of a nested method in class is given below.

class NestedMethods:
    # define class variable
    x = 10
    def outer_method(self, c, d):
        # define inner method
        def operations(a, b):
            print("Sum of numbers", a+b)
            print("Product of numbers", a * b)
            # access instance variable 
            print("Instance variable is", self.x)
        # call inner method
        operations(10, 20)

# create class instance
obj = NestedMethods()
# call outer method
o = obj.outer_method(2,3)

This code will produce following output

Sum of numbers 30
Product of numbers 200
Instance variable is 10

Remember that here also, inner methods can access the variables defined inside outer method as well as class variables(shown in above example) but vice-versa is not possible.
Also, inner method can not be called directly.
Returning values from inner function
A nested function can also return a value to the outer function. As explained above, outer function can not access the values of inner function directly but if an inner function returns a value, the outer function can gain access to the values from inner function.
Example follows

class NestedMethods:
    # define class variable
    x = 10
    def outer_method(self, c, d):
        # define inner method
        def operations(a, b):
            # return value from inner method
            return a + b
        # call inner method
        result = operations(c, d)
        print("Value returned from inner function is", result)

# create object of class
obj = NestedMethods()
# call method
obj.outer_method(2,3)

In this example, inner method adds the values received as argument and returns the result to the outer method. Outer method then prints the result producing the below output.

Value returned from inner function is 5

Returning nested function
All the above examples called inner function directly from outer function but it is also possible to return inner function from outer function and call it later. An example will clarify this.

class NestedMethods:
    def outer_method(self, c, d):
        # define inner method
        def operations(a, b):
            print("Sum of numbers", a+b)
            print("Product of numbers", a * b)
        # return inner method
        return operations

# create instance of class
obj = NestedMethods()
# call outer method and store its return value
inner_method_handle = obj.outer_method(2,3)
inner_method_handle(2,3)

Output will be

Sum of numbers 5
Product of numbers 6

Note that outer method returns inner method without parenthesis. Outer method is called and its return value is stored in a variable.
This variable actually holds reference to the outer method and can be used to call it later. Also, the outer method does not call inner method from inside itself as in the earlier examples.
That is all about nested functions in python.

Leave a Reply