# 10. Functional programming

10. Functional programming
• General example why function required
• When should we go for function?
• What is a Function?
• Types of function
• Pre-defined or built-in functions
• User Defined Functions:
• Function-related terminology
• Function explanation
• Defining a function
• Calling a function
• Function without parameters
• Function with parameters
• return keyword in python
• return vs None
• Returning multiple values from a function
• A function can call other function
• Understandings
• Functions are first class objects
• Assigning a function to a variable
• Pass function as a parameter to another function.
• Define one function inside another function
• a function can return another function
• Formal and actual arguments
• Types of arguments
• Positional arguments
• Keyword arguments
• Default arguments
• a non-default argument follows default argument
• Variable length arguments
• keyword variable length argument (**variable)
• Function vs Module vs Library:
• Types of variables
• Local variables
• Global variables
• The global keyword
• When we can choose global keyword?
• Recursive function
• Anonymous functions or Lambdas
• A simple difference between normal and lambda functions
• Where lambda function fits exactly?
• filter() function
• map() function
• reduce() function
• Function Aliasing
• Function decorators
• Decorator explanation
• Steps to create a decorator
• @ symbol
• Function generators
• next(generator) function
• Programs
10. Functions
General example why function required?
• When you go for walk in the early morning,
1. Get up from the bed,
2. Do fresh up,
3. Tie the shoe,
4. Pick the smooth towel,
5. Start the walk.
• Think of this sequence of steps to do morning walk.
• Now when my dad call for morning walk means, he doesn’t want to explain all these steps each time.
• Whenever dad says, “Get ready for morning walk”, means he is making a function call.
•  ‘Morning walk’ is an abstraction for all the many steps involved.
When should we go for function
Reason 1:
• While writing coding logic, instead of writing like a plain text, it’s good to keep those coding statements in one separate block, because whenever required then we can call these.
Reason 2:
• If a group of statements is repeatedly required, then it is not recommended to write these statements in every time separately.
• So, it’s good to define these statements in a separate block, after defining function we can call directly if required.
•  This block of statements is called as function.
•  Let us understand more by doing practically.
Function
• A function can contain group of statement which performs the task.
• Maintaining the code is an easy way.
• Code reusability.
Make a note
• print() is predefined function in python which prints output on the console.
Types of functions
• There are two types of functions,
• Pre-defined or built-in functions
• User-defined functions
Pre-defined or built-in functions
• The functions which are already coming along with installed python software
Examples
• id()
• type()
•  input()
User Defined Functions:
• The functions which are defined by developer as per the requirement is called as user defined functions.
Make a note
• Till previous chapter we discussed about pre-defined functions like,
• print()
• id() etc.
Make a note
• Now we are going to discuss about user defined functions.
Function related terminology
• def keyword
• name of the function
• parenthesis ()
• parameters (if required)
• colon symbol :
• function body
• return type (optional)
• After defined a function we need to call the function
• If function is parameterized, then pass the values while calling.
Function
• A function can contain mainly two parts,
• Defining function
• Calling function
Defining a function
• def keyword is used to define function.
• After def keyword we should write name of the function.
• After function name, we should write parenthesis ()
•  After parenthesis we should write colon :
• This parenthesis may contain parameters.
• Parameters are just like variables which receives the values.
• If function having parameters, then we need to provide the values while calling.
• Function body.
• Perform the operations.
• Before closing the function, function may contain return type.
 Syntax          def function_name(parameters) :     """ doc string"""     Body of the function to perform operation return value (if required)

 Program      Define a function which have no parameters Name          demo1.py                   def display():                            print(“welcome to function”) output

Make a note
• When we execute above program, then it will not display any output.
•  To see the output we need call the function.
2. Calling a function
• After defining a function, we need to call to execute the function.
• While calling the function, function name should be match otherwise we will get error.
 Program      Define and call the function Name          demo2.py                   def display():                            print(“welcome to function concept”)                   display() output                   welcome to function concept

Make a note
• If we call the function in one time, then one-time function will get execute.
• If we call the function in two times, then two times function will get execute.
• If we call the function in n times, then n times function will get execute.
 Program      Error: calling function name with different name Name          demo3.py                   def one():                            print(“This is one function”)                   two() Error                             NameError: name 'two' is not defined

Functions are two types
• Based on parameters we can divide the functions in two ways,
• Function without parameters
• Function with parameters
Function without parameters
• A function which have no parameters is called function without parameters.
• We can define a function which having no parameters.
 Syntax def nameofthefunction(): body of the function to perform operations

 Program       Function which having no parameters  Name          demo4.py                   # defining a function                   def display1():                            print(“function which having no parameters”)                   # calling function                   display1() output                   function which having no parameters

2. Function with parameters
• A function which having parameters are called parameterised function.
• These parameters are required to process the function operations.
• When we pass parameters then,
• Function can capture or receive the parameter’s values
• Perform the operations by using received values
• Function can print the result.
 Syntax def nameofthefunction(parameter 1, parameter 2, …): body of the function

 Program      Function performing addition operation Name          demo5.py                   # defining the function                   def sum(a, b):                            print(“Sum of two values=”, (a+b))                   #calling the function                   sum(10, 20) output                   Sum of two values =30

 Program      Check a number as it is, even or odd by using function Name          demo6.py          def checking(num):                   if num % 2 == 0:                            print(num,” is even”)                   else:                            print(num,” is odd”)                   checking(12)          checking(31)          output                   12 is even                   31 is odd

return keyword in python
• return is a keyword in python programming language.
• By using return, we can return the result.
• Function can,
• Take input values
• Process the logic
• returns output to the caller with return statement.
 Syntax          def NameOfTheFunction(parameter1, parameter2, …):                   body of the function                   return result

 Program      function returning the value Name          demo7.py                   def sum(a, b):                            c = a + b                            return c                            x=sum(1, 2)                   print(“Sum of two numbers is: ”,x) output                   3

return vs None
• If any function is not return anything, then by default it returns None data type.
• We can also say as, if we are not writing return statement, then default return value is None
 Program      function returning the value Name          demo8.py                   def m1():                            print(“This function is returning nothing”)                   # function calling                   m1()                   # function calling                   x=m1()                   print(x) output                   This function is returning nothing                   This function is returning nothing                   None

Returning multiple values from function
• In python, a function can return multiple values.
• If a function is returning multiple values then we can write return statement as,
 Syntax                   def nameofthefunction() :                            body of the function return multiple values

 Program      Define a function which can return multiple values Name          demo9.py          def m1(a, b):                   c = a+b                   d = a-b                   return c, d          #calling function                   x, y = m1(10, 5)                   print(“sum of a and b: ”, x)                   print(“subtraction of a and b: ”, y) output sum of a and b:  15 subtraction of a and b:  5

Function can call other function
• We can call a function inside another function.
 Syntax                   def firstfunction() :                            body of the first function                                     def secondfunction() :                            body of the second function                            we can call the first function based on requirement

 Program      One function can call another function Name          demo10.py def m1():          print(“first function information”) def m2():          print(“second function information”) m2() output                   second function information

 Program      Calling one function from another function Name          demo11.py def m1():          print(“first function information”) def m2():          print(“second function information”)          m1() m2() output                   second function information                   first function information

Understandings
• We defined two functions m1 and m2
• In function m2, we are calling m1 function.
• So finally, we are calling only m2 function which calls internally m1 function.
Functions are first class objects
• Functions are considered as first-class objects.
• When we create a function, the python interpreter internally creates an object.
• In python, below things are possible to,
• Assign function to variables - (demo12.py)
• Pass function as a parameter to another function - (demo13.py)
• Define one function inside another function - (demo15.py)
• Function can return another function - (demo17.py)
• Assigning a function to variable
 Program      Assign a function to variable Name          demo12.py def add(): print(“We assigned function to variable”) #Assign function to variable sum=add #calling function sum() output We assigned function to variable

• Pass function as a parameter to another function.
 Program      Pass function as a parameter to another function                  Name          demo13.py def display(x):          print("This is display function")          def message():          print("This is message function")          # calling function message() output                   This is message function

 Program      Pass function as a parameter to another function                  Name          demo14.py def display(x):          print("This is display function")          def message():          print("This is message function")          # calling function message() display(10) output                   This is message function                   This is display function

 Program      Pass function as a parameter to another function                  Name          demo15.py def display(x):          print("This is display function")          def message():          print("This is message function")          # calling function display(message()) output                   This is message function                   This is display function

• Define one function inside another function
 Program      function inside another function Name          demo16.py def first():          print("This is outer function")          def second():                   print("this is inner function")          second() #calling outer function first() output                   This is outer function this is inner function

Make a note
• If we defined inner function, then we need to call that inner function in outer function.
• function can return another function
 Program      function can return another function Name          demo17.py def first():          def second():                   print("This function is return type to outer function")          return second x=first() x() Output                   This function is return type to outer function

Formal and actual arguments
• When a function is defined it may have some parameters.
• These parameters receive the values.
• Parameters are called as a ‘formal arguments’
• When we call the function, we should pass values or data to the function.
• These values are called as ‘actual arguments
 Program      Formal and actual arguments Name          demo18.py def sum(a, b): c = a + b          print(c) # call the function x = 10 y = 15 sum(x, y) output                   25

• a and b called as formal arguments
• x and y called actual arguments
Types of arguments
• In python there are 4 types of actual arguments are existing,
• positional arguments
• keyword arguments
• default arguments
• variable length arguments
Positional arguments
• These are the arguments passed to a function in correct positional order.
• The number of arguments and position of arguments should be matched, otherwise we will get error.
 Program      Positional arguments Name          demo19.py                   def sub(x, y):                   print(x-y)                   # calling function          sub(10, 20) output                   -10

Make a note
• If we change the number of arguments, then we will get error.
• This function accepts only two arguments then if we are trying to provide three values then we will get error.
 Program      Error: Positional arguments Name          demo20.py          def sub(x, y):                   print(x-y)                   # calling function          sub(10, 20, 30) output TypeError: sub() takes 2 positional arguments but 3 were      given

2. Keyword arguments
• Keyword arguments are arguments that recognize the parameters by the name of the parameters.
• Example: Name of the function is cart() and parameters are item and price can be written as:
•  def cart(item, price)
• At the time of calling this function, we must pass two values and we can write which value is for what by using name of the parameter, for example
• cart(item=’bangles’, price=20000)
• cart(item=’handbag’, price=100000)
• item and price are called as keywords in this scenario.
• Here we can change the order of arguments.
 Program      keyword arguments Name          demo21.py          def cart(item, price):                   print(item, ”cost is :” ,price)                   # calling function cart(item=’bangles’, price=20000)      cart(item=’handbag’, price=100000) cart(price=1200, item=’shirt’)   output bangles cost is: 20000 handbag cost is: 100000 shirt cost is: 1200

 Program      keyword arguments Name          demo22.py          def details(id, name):                   print(“Emp id is: ”,id)                   print(“Emp name is: ”,name)                   # calling function details(id=1, name=’Balayya Babu’)    details(id=2, name=’Chiru’)      output Emp id is:  1 Emp name is:  Balayya Babu Emp id is:  2 Emp name is:  Chiru

Make a note
• We can use both positional and keyword arguments simultaneously.
• But first we must take positional arguments and then keyword arguments, otherwise we will get syntax error.
 Program      positional and keyword arguments Name          demo23.py          def details(id, name):                   print(“Emp id is: ”,id)                   print(“Emp name is: ”,name)          details(1, name=‘Nireekshan’) output Emp id is:  1 Emp name is:  Nireekshan

 Program      Error: positional and keyword arguments Name          demo24.py          def details(id, name):                   print(“Emp id is: ”,id)                   print(“Emp name is: ”,name)          details(name=‘Nireekshan’, 1) Error SyntaxError: positional argument follows keyword argument

3. Default arguments
• We can provide some default values for the function parameters in the definition.
• Let’s take the function name as cart(item, price=40.0) (Example: In few shops any item is 10 rupees)
• cases
• In above example item have no default value, so we should provide.
• price have default value as 40
• still if we provide the value at time of calling then default values will be override with passing value.
 Program      Default arguments Name          demo25.py          def cart(item, price = 40.0):                   print(item, ”cost is: ”,price)                   # calling function cart(item=’pen’)                      cart(item=’handbag’, price=10000)              cart(price=500, item=’shirt’) output pen cost is: 40.0 handbag cost is: 10000 shirt cost is: 500

Make a note
• If we are not passing any value, then only default value will be considered.
non-default argument follows default argument
• While defining a function, after default arguments we should not take non-default arguments
 Program      SyntaxError: non-default argument follows default argument Name          demo26.py          def m1(a=10, b):                   print(a)                   print(b)                   # calling function m1(b=20) Error                   SyntaxError: non-default argument follows default argument

4. Variable length arguments
• Sometimes, the programmer does not know how many values need to pass to function.
• In that case, the programmer cannot decide how many arguments to be given in the function definition.
• totalcost(item1_cost, item2_cost)  =>    totalcost(1, 2) #    valid
• totalcost(item1_cost, item2_cost)  =>    totalcost(1, 2, 3) # Invalid
• To accept ‘n’ number of arguments, we need to use variable length argument.
• The variable length argument is an argument that can accept any number of values.
• The variable length argument is written with a ‘*’ (one star) before variable in function definition.
 Syntax def nameofthefunction(x, *y): body of the function
• x is formal argument
• *y is variable length argument
• Now we can pass any number of values to this *y.
• Internally the provided values will be represented in tuple.
 Program      Variable length argument Name          demo27.py                   def totalcost(x, *y):                            sum=0                            for i in y:                                     sum+=i                            print(x + sum)                   #calling function                            totalcost(100, 200)          #      valid                   totalcost(110, 226, 311)   #      valid                   totalcost(11,)                   #      valid output 300 647 11

keyword variable length argument (**variable)

 Syntax        def m1(**x):         body of the function

•  **x represents as keyword variable argument
• Internally it represents like a dictionary object
• dictionary stores the data in the form of key value pairs.
 Program      keyword variable length argument (**variable) Name          demo.py def print_kwargs(**kwargs):          print(kwargs) print_kwargs(id=1, name="Nireekshan", qualification="MCA") Output {'id': 1, 'name': 'Nireekshan', 'qualification': 'MCA'}

 Program      keyword variable length argument (**variable) Name          demo28.py def m1(**x): for k, v in x.items(): print(k,"=",v) m1(a=10, b=20, c=30) m1(id=100, name="Subbalaxmi") output a = 10 b = 20 c = 30 id = 100 name = Subbalaxmi

Types of variables
• Python supports two types of variables.
• Local variables
• Global variables
Local variables
• The variables which are declared inside of the function are called as local variable.
• We can access local variables within the function only.
• Error: If we are trying to access local variables in outside of the function, then we will get error.
 Program      local variables Name          demo29.py                   def m():                            a=11                            print(a)                   m() output                   11

 Program      NameError: name 'a' is not defined Name          demo30.py                   def m():                            a=11                            print(a)                   def n():                            print(a)                            m()                   n() output                   NameError: name 'a' is not defined

2. Global variables
• The variables which are declared outside of the function are called as global variable.
• Global variables can be accessed in all functions of that module.
 Program      global variables Name          demo31.py                   a=11                   b=12                   def m():                            print(“a from function m(): ”,a)                            print(“b from function m(): ”,b)          def n():                            print(“a from function n(): ”,a)                            print(“b from function n(): ”,b)                   m()                   n()          output a from function m(): 11 b from function m(): 12 a from function n(): 11 b from function n(): 12

The global keyword
• We can use global keyword for the following 2 purposes:
• To declare global variable inside function
• To make global variable available to the function.
When we can choose global keyword?
• Sometimes the global variable names and local variable names can contain same name.
• In that case, function by default refers local variable and ignores the global variable.
• So, the global variable is not accessible inside the function but still outside is accessible.
 Program      global and local variables having same name Name          demo32.py          a=1          def m1():                   a=2                   print(“a value from m1() function: ”, a)          def m2():                   print(“a value from m2() function:”, a)          m1()          m2() output                   a value from m1() function: 2                   a value from m2() function: 1

• If programmer wants to use the global variable inside a function, then need to use global keyword before the variable in the beginning of the function body.
 Program       global and local variables having same name Name          demo32.py          a=1          def m1():                   global a                   a=2                   print(“a value from m1() function: ”, a)          def m2():                   print(“a value from m2() function:”, a)          m1()          m2() output                   a value from m1() function: 2                   a value from m2() function: 2

Make a note
• If we use global keyword inside function, then function can able to read only global variable.
Limitation
• Now, local variable is no more available now.
Solution
• The globals() function will solve this problem.
• globals() is a built in function which returns a table of current global variables in the form of a dictionary.
• Using this function, we can refer to the global variable ‘a’ as: global()[‘a’].
 Program      global and local variable names same Name          demo34.py                   a=1                   def m():                            a=2                            print(a)                            print(globals()[‘a’])                   m() output                   2                   1

Recursive function
• If a function calls that function itself, then it is called as recursive function
Example
3!      =       3*2*1

factorial(3) = 3 * factorial(2)
factorial(2) = 3 * 2 * factorial(1)
factorial(1) = 3 * 2 * 1 * factorial(0)

factorial(n) = n * factorial(n-1)

• We can reduce length of the code and improves readability
• We can solve complex problems in very easy way.
 Program      factorial using recursion Name          demo35.py                   def factorial(n):                            if n ==0:                                     result=1                            else:                                     result = n * factorial(n-1)                            return result                   x= factorial(4)                   print(“Factorial of 4 is: ”,x) output                   24

 Program       Factorial without using recursive function Name          demo.py def f1():          n=4          fact=1          while(n>0):                   fact=fact*n                   n=n-1          print("Factorial of the number is: ", fact) f1() Output                   Factorial of the number is:  24

Anonymous functions or Lambdas
• A function without a name is called as anonymous function.
• Generally, to define normal function we need to use def keyword.
• To define anonymous function, we need to use lambda keyword.
Lambda function

 Syntax                   lambda argument_list: expression

• By using Lambda Functions, we can write very concise code so that readability of the program will be improved.
 Program      anonymous function Name          demo36.py                   s = lambda a: a*a x=s(4) print(x) output 16
• Here because of lambda keyword it creates anonymous function.
A simple difference between normal and lambda functions

 Program      To find square by using a normal function               Name          demo37.py               def square(t):                        return t*t               s=square(2) print(s)          output                   4

 Program      To find sum of two values by using normal function Name          demo39.py def add(x, y):          return x + y b=add(2, 3) print(b) output 5

 Program      To find sum of two values by using anonymous function Name          demo40.py add=lambda x, y: x+y                   result = add(1, 2)                   print(‘The sum of value is: ’, result) output 3

Make notes
• Lambda Function internally returns expression value and we no need to write return statement explicitly.
Where lambda function fits exactly?
• 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, these functions expect function as argument.
filter() function
• Based on some condition we can filter values from sequence of values.
• Where function argument is responsible to perform conditional check, sequence can be list or tuple or string.
 Syntax                   filter(function, sequence)

 Program      example by using filter function Name          demo41.py items_cost = [999, 888, 1100, 1200, 1300, 777] gt_thousand = filter(lambda x : x>1000, items_cost) x=list(gt_thousand) print("Eligible for discount: ",x) output                   Eligible for discount : [1100, 1200, 1300]

map() function
• The map() function can apply the condition on every element which is available in the sequence of elements.
• After applying map function can generate new group of values
 Syntax                   map(function, sequence)

 Program      Find square by using map function Name          demo42.py without_gst_cost = [100, 200, 300, 400] with_gst_cost = map(lambda x: x+10, without_gst_cost) x=list(with_gst_cost) print("Without GST items costs: ",without_gst_cost) print("With GST items costs: ",x)                   output Without GST items costs:  [100, 200, 300, 400] With GST items costs:  [110, 210, 310, 410]

reduce() function
• reduce() function reduces sequence of elements into a single element by applying the specific condition or logic.
• reduce() function present in functools module.
• So, to work with reduce we need to import functools module.
 Syntax reduce(function, sequence)

 Program      reduce function Name          demo43.py from functools import reduce each_items_costs = [111, 222, 333, 444] total_cost = reduce(lambda x, y: x+y, each_items_costs) print(total_cost) output                   1110

Function Aliasing
• We can give another name for existing function, this is called as function aliasing.
 Program      function aliasing Name          demo44.py def a():                            print(“function - a”) b=a b() output                   function - a

Function decorators
• Nested function
• Functions are first class objects.
Decorator explanation
• A decorator is a function that accepts a function as parameter and returns a function.
• Decorators are useful to perform some additional processing required by a function.
Steps to create decorator
• Step 1:
• decorator function takes parameter as another function
 Syntax                   def decor(number):                            body of decorator function

• Step 2:
• We should define inner function inside the decorator function.
• This function modifies or decorates the value of the function passed to the decorator function.
 Basic code                   def decor(number):                            def inner():                                     value = number ()                                     return value + 2                            return inner
• Step 3:
• Return the inner function that has processed the value.
• Step 4:
• After decorator created then we can call where are all required.
• While calling decorator function we need to pass parameter as a function.
 Basic code def num():          return 10 #calling decorator result = decor(num) print(result)

 Program      Creating decorator Name          demo45.py def m1(number): def m2(): x = number() return x + 2 return m2 def m3(): return 10 result = m1(m3) print(result()) output 12

@ symbol
• Syntactic Sugar, Python allows you to simplify the calling of decorators using the @ symbol (this is called “pie” syntax).
• To apply decorator to any function we can use the @ symbol and decorator name on top of the function name.
 @decor def m3():          return 10

• When we are using @ symbol then we no need to call decorator explicitly and pass the function name.
• We can call directly like,
• print(m3())
 Program      @symbol using on decorator Name          demo46.py def m1(n):          def m2():                   value = n()                   return value + 2          return m2 @m1 def m3():          return 10 print(m3()) output 12

Function generators
• Generators are just like functions that return a sequence of values.
• A generator function is written like an ordinary function, but it uses yield keyword.
 Program      Generator example Name          dem47.py def m():          yield 'Prasad'          yield 'Nireekshan' g = m() print(g) print(type(g)) for y in g:          print(y) output                                                       Prasad                   Nireekshan

 Program      Generator example Name          demo48.py                   def m(x, y):                            while x<=y:                                     yield x                                     x+=1                   g = m(5, 10)                   for y in g:                            print(y) output                   5                   6                   7                   8                   9                   10

next(generator) function
• If we want to retrieve elements from generator we can use next(generator) function.
 Program      Generator example Name          dem49.py def m():          yield 'Prasad'          yield 'Nireekshan' g = m() print(type(g)) print(next(g)) print(next(g)) output                                     Prasad                   Nireekshan