Before reading this article, I recommend to read the below two articles to understand better.
Nested Functions
- Nested functions are functions defined within other functions.
- Nested functions can read variables declared in the immeditely outside function
>>> x = 10
>>> def outer():
... y = 20
... def inner():
... x = 30
... y = 40
... z = 50
... print("X ="+ str(x))
... print("Y ="+ str(y))
... print("Z ="+ str(z))
... inner()
... print("Y =" + str(y))
...
>>> outer()
X =30
Y =40
Z =50
Y =20
>>> x
10
Nested Function using Global and Non Local
>>> x = 10
>>> def outer():
... y = 20
... def inner():
... global x
... x = 30
... nonlocal y
... y = 40
... z = 50
... print(f"x = {x}, y = {y}, z = {z}")
... inner()
... print(f"y ={y}")
...
>>> outer()
x = 30, y = 40, z = 50
y =40
>>>
>>> def outer(num):
... def inner():
... print(num)
... inner()
...
>>> outer(10)
10
Closure Function.
A closure is a nested function with an after-return access to the data of the outer function, where the nested function is returned by the outer function as a function object.
- We should have nested function.
- Nested function has to refer to a variable defined inside the enclosing function.
- Enclosing function must return the nested function.
>>> def outer(num):
... def inner():
... print(num)
... return inner
...
>>> myfun = outer(999)
>>> myfun()
999
>>> num = 1010101
>>> myfun()
999
>>> del outer
>>> myfun()
999
>>> def outer(num1):
... def inner(num2):
... return num1 * num2
... return inner
...
>>> myfun = outer(10)
>>> myfun(20)
200
>>> def factouter():
... def factinner(n):
... if n==1:
... return 1
... else:
... return n * factinner(n-1)
... return factinner
...
>>> myfact = factouter()
>>> myfact(10)
3628800
>>> myfact(5)
120
Using Non Local variables inside Inner Function for the variables defined in the enclosing scope
>>> def outer(x):
... y = 10
... def inner(z):
... nonlocal y
... return x*y*z
... return inner
...
>>> myfun = outer(8)
>>> myfun(5)
400
Passing Functions to Closure Function
>>> def outer(funobj):
... def inner(str):
... funobj(str)
... return inner
...
>>> def display(name):
... print(name)
...
>>> myfun = outer(display)
>>> myfun("Girish")
Girish
In the below example, I have created a Multiplication Table Printing Function which takes table number and maximum multiplier number as input. The function object is passed to the closure function.
>>> def mul(table, n):
... for x in range(1,n+1):
... print(f" {table} x {x} = {x*table}")
...
>>> def outer(funobj):
... def inner(table,max):
... funobj(table,max)
... return inner
...
>>> myfun = outer(mul)
>>> myfun(9,15)
9 x 1 = 9
9 x 2 = 18
9 x 3 = 27
9 x 4 = 36
9 x 5 = 45
9 x 6 = 54
9 x 7 = 63
9 x 8 = 72
9 x 9 = 81
9 x 10 = 90
9 x 11 = 99
9 x 12 = 108
9 x 13 = 117
9 x 14 = 126
9 x 15 = 135
References
- https://docs.python.org/3/faq/programming.html
- https://www.python.org/dev/peps/pep-0227/
- https://www.python.org/dev/peps/pep-3104/#new-syntax-in-the-referring-inner-scope
Learn more about Python features in our upcoming blog articles.
Happy Learning!