**Recursive Functions**

A function that calls itself is known as Recursive Function.

Ex: factorial(3)=3*factorial(2)=3*2*factorial(1)=3*2*1*factorial(0) =3*2*1*1 =6factorial(n)= nfactorial(n-1)

The main advantages of recursive functions are:

- We can reduce length of the code and improves readability
- We can solve complex problems very easily.

**Q. Write a Python Function to find factorial of given number with recursion.**

def factorial(n):

if n==0:

result=1

else:

result=n*factorial(n-1)

return result

print(“Factorial of 4 is :”,factorial(4))

print(“Factorial of 5 is :”,factorial(5))

**Output**Factorial of 4 is : 24

Factorial of 5 is : 120

__Anonymous Functions:__

Sometimes we can declare a function without any name,such type of nameless functions are called anonymous functions or lambda functions.

The main purpose of anonymous function is just for instant use(i.e for one time usage)

**Normal Function:**

We can define by using def keyword.

def squareIt(n):

return n*n

__lambda Function:__

We can define by using lambda keyword

lambda n:n*n

Syntax of lambda Function:lambda argument_list : expression

**Note:**By using Lambda Functions we can write very concise code so that readability of the program will be improved.

**Q. Write a program to create a lambda function to find square of given number?**s=lambda n:n*n

print(“The Square of 4 is :”,s(4))

print(“The Square of 5 is :”,s(5))

**Output**The Square of 4 is : 16

The Square of 5 is : 25

**Lambda function to find sum of 2 given numbers**s=lambda a,b:a+b

print(“The Sum of 10,20 is:”,s(10,20))

print(“The Sum of 100,200 is:”,s(100,200))

Output

The Sum of 10,20 is: 30

The Sum of 100,200 is: 300

**Lambda Function to find biggest of given values.**s=lambda a,b:a if a>b else b

print(“The Biggest of 10,20 is:”,s(10,20))

print(“The Biggest of 100,200 is:”,s(100,200))

Output

The Biggest of 10,20 is: 20

The Biggest of 100,200 is: 200

**Note:**Lambda Function internally returns expression value and we are not required to write return statement explicitly.

**Note:**Sometimes we can pass function as argument to another function. In such cases lambda functions are best choice.

We can use lambda functions very commonly with filter(),map() and reduce() functions,b’z these functions expect function as argument.

__filter() function:__

We can use filter() function to filter values from the given sequence based on some condition.

filter(function,sequence)

where function argument is responsible to perform conditional check sequence can be list or tuple or string.

**Q. Program to filter only even numbers from the list by using filter() function?**

**without lambda Function:**def isEven(x):

if x%2==0:

return True

else:

return False

l=[0,5,10,15,20,25,30]

l1=list(filter(isEven,l))

print(l1) #[0,10,20,30]

**with lambda Function:**l=[0,5,10,15,20,25,30]

l1=list(filter(lambda x:x%2==0,l))

print(l1) #[0,10,20,30]

l2=list(filter(lambda x:x%2!=0,l))

print(l2) #[5,15,25]

__map() function:__

For every element present in the given sequence,apply some functionality and generate new element with the required modification. For this requirement we should go for map() function.

Ex: For every element present in the list perform double and generate new list of doubles.

Syntax: map(function,sequence)

The function can be applied on each element of sequence and generates new sequence.

**Ex: Without lambda**l=[1,2,3,4,5]

def doubleIt(x):

return 2*x

l1=list(map(doubleIt,l))

print(l1) #[2, 4, 6, 8, 10]

**with lambda**l=[1,2,3,4,5]

l1=list(map(lambda x:2*x,l))

print(l1) #[2, 4, 6, 8, 10]

**Ex 2: To find square of given numbers**l=[1,2,3,4,5]

l1=list(map(lambda x:x*x,l))

print(l1) #[1, 4, 9, 16, 25]

We can apply map() function on multiple lists also.But make sure all list should have same length.

Syntax: map(lambda x,y:x*y,l1,l2))x is from l1 and y is from l2

**Ex:**l1=[1,2,3,4]

l2=[2,3,4,5]

l3=list(map(lambda x,y:x*y,l1,l2))

print(l3) #[2, 6, 12, 20]

__reduce() function:__

reduce() function reduces sequence of elements into a single element by applying the specified function.

reduce(function,sequence)

**reduce() function present in functools module and hence we should write import statement.**

**Ex:**from functools import *

l=[10,20,30,40,50]

result=reduce(lambda x,y:x+y,l)

print(result) # 150

**Ex:**result=reduce(lambda x,y:x*y,l)

print(result) #12000000

**Ex:**from functools import *

result=reduce(lambda x,y:x+y,range(1,101))

print(result) #5050

**Note:**

- In Python every thing is treated as object.
- Even functions also internally treated as objects only.

**Ex:**def f1():

print(“Hello”)

print(f1)

print(id(f1))

**Output**<function f1 at 0x00419618>

4298264

**Function Aliasing:**

For the existing function we can give another name, which is nothing but function aliasing.

**Ex**:

def wish(name):

print(“Good Morning:”,name)

greeting=wish

print(id(wish))

print(id(greeting))

greeting(‘SEED’)

wish(‘SEED’)

**Output**4429336

4429336

Good Morning: SEED

Good Morning: SEED

**Note**:

- In the above example only one function is available but we can call that function by using either wish name or greeting name.
- If we delete one name still we can access that function by using alias name

**Ex:**def wish(name):

print(“Good Morning:”,name)

greeting=wish

greeting(‘Dharshi’)

wish(‘Dharshi’)

del wish

#wish(‘Dharshi’) ==>NameError: name ‘wish’ is not defined

greeting(‘Shishir’)

**Output**Good Morning: Dharshi

Good Morning: Dharshi

Good Morning: Shishir

**Nested Functions:**

We can declare a function inside another function, such type of functions are called Nested functions.

**Ex:**def outer():

print(“outer function started”)

def inner():

print(“inner function execution”)

print(“outer function calling inner function”)

inner()

outer()

#inner() ==>NameError: name ‘inner’ is not defined

**Output**outer function started

outer function calling inner function

inner function execution

In the above example inner() function is local to outer() function and hence it is not possible to call directly from outside of outer() function.

**Note**: A function can return another function.

**Ex:**def outer():

print(“outer function started”)

def inner():

print(“inner function execution”)

print(“outer function returning inner function”)

return inner

f1=outer()

f1()

f1()

f1()

**Output**outer function started

outer function returning inner function

inner function execution

inner function execution

inner function execution

**Q. What is the difference between the following lines?**f1 = outer

f1 = outer()

In the first case for the outer() function we are providing another name f1(function aliasing).

But in the second case we calling outer() function, which returns inner function. For that inner function() we are providing another name f1

**Note:** We can pass function as argument to another function

**Ex**: filter(function,sequence)

map(function,sequence)

reduce(function,sequence)