Wednesday 15 May 2019

10. Functional programming

 10. Functional programming
    • General example why function required
    • When should we go for function?
    • What is a Function?
    • Advantage of 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
    • Advantage
    • 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.
Advantages
  • 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)

Advantage
  • 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


Advantage
  • 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        
  • Before understanding about function decorator, we need to understand about,
  • Nested function
    • We already discussed previously.
  • Functions are first class objects.
    • We already discussed previously
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
                  <generator object m at 0x000002AA28E97938>
                  <class 'generator'>
                  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
                  <class ‘generator’>
                  Prasad
                  Nireekshan