Python nested function

In another post, we have discussed how to declare and define a function in Python, in this post, we will see how to define another type of function, which is the Python nested function.

When we say nested function, we are referring to the function defined under another function. So nested function are always found inside another function. Look at the code below.

>>> def func():
...  ns=901
...  def foo(): #nested function
...   lc=120
...   print('lc=',lc)
...  print('ns=',ns)
...

In the above code, the function func() is the outer function, the function foo() defined under func() is the nested function.


Many nested functions inside a fucntion

There can be many nested functions inside a function. There can be many nested functions inside a function.

>>> def func():
...  v=90
...  def f1(): #Nested function 1
...   v1=1
...  def f2(): #Nested function 2
...   v2=10
...  def f3(): #Nested function 3
...   v3=18
...  print("v=",v)
...
>>> func()
v= 90

In the above code, the function func() has three nested functions: f1(), f2() and f3().


How to call a nested function

To execute a nested function we have to call the nested function inside the function in which the nested function has been defined. We can call the nested function only inside the function in which the nested function is defined. Calling outside the function is not allowed.

Consider the code below.

>>> def func():
...  var=90
...  def foo(): #nested function
...   ns=100
...   print("Inside foo(), ns=",ns)
...   print("Inside foo(), var=",var)
...  foo() # Calling foo() nested function
...  print("Inside func(), var=",var)
...
>>> func()
Inside foo(), ns= 100
Inside foo(), var= 90
Inside func(), var= 90
>>> foo() 

We called foo() inside the func(), so the foo() is executed smoothly. After foo() function is executed whatever code is present after the foo() call is executed. In our case, we have the code “print(“Inside func(), var=”,var)“, so it is executed.

In the last line of the code above, we tried calling foo() outside the func(), but the call fails and you will get the error message as,
 
Traceback (most recent call last):
File ““, line 1, in
NameError: name ‘foo’ is not defined
“.
 
Note the line “NameError: name ‘foo’ is not defined“, the error simply means the foo() function it not callable outside the function func().

Calling many nested functions

If there are many nested functions, to execute each function we have to call them individually. The order of execution is determine by the order of the call. Whichever is called first will be executed first and the function called next will be executed next and so on.

>>> def func():
...  v=19
...  def f1():
...   v1=10
...   print("Inside f1(), v1=",v1)
...  def f2():
...   v2=20
...   print("Inside f2(), v2=",v2)
...  def f3():
...   v3=30
...   print("Inside f3(), v3=",v3)
...  f2()
...  f1()
...  f3()
...  print("Inside func(), v=",v)
...
>>> func()
Inside f2(), v2= 20
Inside f1(), v1= 10
Inside f3(), v3= 30
Inside func(), v= 19

Inside func() the order of the call is f2(), f1() and f3(), so the order of execution also follows that order.


The nested function scope

The nested functions have their own scope and they are known as local scopes. And the scope of the outer function surrounding the local scopes is known as nested scope.

Each local scope of the nested function are not shared with any other scopes. And since the scope is not shared, any variables or objects defined under a particular local scope is accessible only inside that scope. If an attempt is made to refer to a local scope variable outside the local scope you will get an error.

Python nested function scope

Each of the function f1(), f2() and f3() scope is marked by different color lines. The variable ‘v’ in each f1(), f2() and f3() local scope is different. That is why ‘v’ outputs different value in each scope.

Also note, outside all the local scopes the value of ‘v’ is referred from the ‘v=100’ of the nested scope.


Changing the nested scope variable value in local scope

We cannot change the value of the nested scope variable in the local scopes. If we ever wish to change the value, we have to declare the nested scope variable with the ‘nonlocal‘ keyword first.

 
>>> def func():
...  var=190
...  def foo():
...   var=1000
...   print("Inside foo(), var=",var)
...  foo()
...  print("Outside foo(), var=",var)
...
>>> func()
Inside foo(), var= 1000
Outside foo(), var= 190

Inside foo(), we have assigned 1000 to ‘var’, but the change is not visible outside foo().

To make ‘var’ retain its value to 1000 outside foo(), we must declare it with the nonlocal statement first. An example is given below.

 def func():
...  var=190
...  def foo():
...   nonlocal var #Note!!
...   var=1000
...   print("Inside foo(), var=",var)
...  foo()
...  print("Outside foo(), var=",var)
...
>>> func()
Inside foo(), var= 1000
Outside foo(), var= 1000

Now the change is visible even outside foo().

More about nonlocal statement here Python nonlocal statement.


*Side note

There can be nested functions inside nested functions. There is no hard and fast rule that prevents nested function to have more nested functions. You can put nested function under nested function under nested function and so on.

def func():
...  va=90
...  def foo():
...   v=1920
...   def foo1():
...    v=635
...    print("Inside foo1(), v=",v)
...   foo1()
...   print("Inside foo(), v=",v)
...  foo()
...  print("Inside func(), va=",va)
...
>>> func()
Inside foo1(), v= 635
Inside foo(), v= 1920
Inside func(), va= 90

The function foo1() is the nested function of foo() and the foo() is the nested function of func().




Leave a Reply

Your email address will not be published. Required fields are marked *