Functional Programming
Functional Programming
Course Outcome
Functional Programming
Functional Programming is a programming paradigm with software primarily composed of functions processing data throughout its
execution.
Python allows us to code in a functional, declarative style.
It even has support for many common functional features like Lambda Expressions ,the map and filter functions.
Functional programming languages are designed on the concept of mathematical functions that use conditional expressions and
recursion to perform computation.
It supports higher-order functions and lazy evaluation features.
It uses the functions and functional calls.
Like OOP, it supports popular concepts such as Abstraction, Encapsulation, Inheritance, and Polymorphism
Bugs-Free Code
It does not support state, so there are no side-effect results and thus error-free codes can be written.
Efficient Parallel Programming
It has NO Mutable state, so there are no state-change issues. One can program "Functions" to work parallel as "instructions". Such
codes support easy reusability and testability.
Efficiency
It consists of independent units that can run concurrently. As a result, such programs are more efficient.
Supports Nested Functions
Functional programming supports Nested Functions.
Lazy Evaluation
Functional programming supports Lazy Functional Constructs like Lazy Lists, Lazy Maps, etc.
Comprehension
Python provides compact syntax for deriving one list from another. These expressions are called list comprehensions.
List comprehensions are one of the most powerful tools in Python.
Python’s list comprehension is an example of the language’s support for functional programming concepts.
The Python list comprehensions are a very easy way to apply a function or filter to a list of items.
Above is equivalent to
for element in iterable:
if condition:
expr
In [1]:
#USING FOR LOOP
evens = []
for i in range(10):
if i % 2 == 0:
evens.append(i)
print(evens)
[0, 2, 4, 6, 8]
In [2]:
# A better and faster way to write the above code
# is through list comprehension.
evens = [i for i in range(10) if i % 2 ==0]
print(evens)
[0, 2, 4, 6, 8]
In [6]:
lst = [i**2 for i in range(1,21) if i%2==0]
print(lst)
[4, 16, 36, 64, 100, 144, 196, 256, 324, 400]
List comprehensions are clearer than the map built-in function for simple cases.
The map requires creating a lambda function for the computation, which is visually noisy.
In [10]:
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
it = map(lambda x: x**2, lst)
newlist = list(it)
print(newlist)
In [12]:
# To compute the squares of the numbers that are divisible by 2.
lst=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_squares = [x**2 for x in lst if x % 2 == 0]
print(even_squares)
In [13]:
num_list = [y for y in range(100) if y % 2 == 0 if y % 5 == 0]
print(num_list)
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
In [14]:
obj = ["Even" if i%2==0 else "Odd" for i in range(10)]
print(obj)
['Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd', 'Even', 'Odd']
In [6]:
# Matrix Transpose using nested loop
T = []
M = [[1, 2, 3, 4], [4, 5, 6, 8]]
for i in range(len(M[0])):
T_row = []
for row in M:
T_row.append(row[i])
T.append(T_row)
print(T)
In [8]:
# Nested list comprehension
localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 7/14
5/24/22, 9:54 PM Functional Programming
M = [[1, 2], [3,4], [5,6], [7,8]]
T = [[row[i] for row in M] for i in range(len(M[0]))]
print (T)
In [ ]:
l1 = [[1,2,3],[4,5,6]]
l2 = [[3,4,5],[1,2,0]]
l3 = l1 + l2
print(l3)
In [4]:
# Matrix Addition
l1 = [[1,2,3],[4,5,6]]
l2 = [[3,4,5],[1,2,0]]
l3 = []
for i in range(len(l1)): # range(3)...,i=0,1,2
tr = []
for j in range(len(l1[0])):
tr.append(l1[i][j] + l2[i][j])
l3.append(tr)
print(l3)
In [3]:
l1 = [[1,2,3],[4,5,6]]
l2 = [[3,4,5],[1,2,0]]
l3 = [[l1[i][j]+l2[i][j] for j in range(3)] for i in range(len(l1))]
print(l3)
In [ ]:
l1 = [[1,2,3],[4,5,6]]
l2 = [[3,4,5],[1,2,0]]
l3 = [[l1[i][j]-l2[i][j] for j in range(len(l1[0]))] for i in range(len(l1))]
print(l3)
key: value pairs is required to create a dictionary. To get these key-value pairs using dictionary comprehension the general statement
of dictionary comprehension is as follows:
localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 8/14
5/24/22, 9:54 PM Functional Programming
In [9]:
# creating the dictionary
squares = {i: i ** 2 for i in range(10)}
print(squares)
In [10]:
keys = ['a', 'b', 'c', 'd']
values = [1, 2, 3, 4]
# creating a dict from the above lists
d = {key: value for (key, value) in zip(keys, values)}
print(d)
In [11]:
mylist = [1, 2, 3, 4, 4, 5, 6, 6, 6, 7, 7]
myset = set()
# Using loop for constructing myset
for var in mylist:
if var % 2 == 0:
myset.add(var)
print("Set using for loop:",myset)
In [12]:
# Using Set comprehensions
mylist = [1, 2, 3, 4, 4, 5, 6, 6, 6, 7, 7]
myset = {var for var in mylist if var % 2 == 0}
print("Set using set comprehensions:", myset)
CLOSURE
A closure is a nested function which has access to a free variable from an enclosing function that has finished its execution. Three
characteristics of a Python closure are:
It is a nested function
It has access to a free variable in outer scope
It is returned from the enclosing function
A free variable is a variable that is not bound in the local scope
Python closures help avoiding the usage of global values and provide some form of data hiding.
In [24]:
# Example : Nested function
# When a function is defined inside another function.
def outerfunc():
x = 10
def innerfunc():
print(x)
innerfunc()
outerfunc()
10
inner() could read the variable ‘x’, which is nonlocal to it. And if it must modify ‘x’, we declare that it’s nonlocal to inner()
In [15]:
# Definition a closure:
def outer(x):
def inner():
print('Value :',x)
return inner # Return the inner function object reference
myfun=outer(7)
myfun()
Value : 7
Python closure is used when a nested function references a value in its enclosing scope.
While it seems like a very simple concept, a closure in python3 helps in the following ways:
With Python closure, it doesn’t need to use global values. This is because they can refer to nonlocal variables. A closure then
provides some form of data hiding.
When code has only a few Python methods (usually, only one), it may use a Python3 closure instead of implementing a class for
that. This makes it easier on the programmer.
A closure, allows to implement a Python decorator.
A closure allows to invoke Python function outside its scope.
Decorators
A decorator is a design pattern in Python that allows a user to add new functionality to an existing object without modifying its
structure.
Decorators are usually called before the definition of a function.
In [25]:
# Using function call
# newdesign function decorates the fun()--olddesign() function
def newdesign(fun):
def inner(): # Wrapper function.
print("################")
fun()
print("################")
return inner
def olddesign():
print("Old details")
# Decorating the olddesign using newdesign
olddesign = newdesign(olddesign)
olddesign()
################
Old details
################
In [26]:
# Using @
# newdesign function decorates the fun()--olddesign() function
localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 11/14
5/24/22, 9:54 PM Functional Programming
def newdesign(fun):
def inner(): # Wrapper function.
print("++++++++++++++++")
fun()
print("++++++++++++++++")
return inner
++++++++++++++++
Old details
++++++++++++++++
In [27]:
print(olddesign.__name__)
inner
s = add(12,45)
print(s)
SUM = 57
In [29]:
def smartdivide(fun):
def inner(a,b):
print(a,"is going to be divided by",b)
if b == 0:
return "division is not possible"
return fun(a,b)
return inner
@smartdivide
def div(x,y):
return x/y
print(div(5,2))
print(div(4,0))
5 is going to be divided by 2
2.5
4 is going to be divided by 0
division is not possible
@split_dec
@upper_dec
def myfun():
return "Hello Students"
myfun()
['HELLO', 'STUDENTS']
Out[30]:
In [32]:
myfun.__name__
'inner'
Out[32]:
class Student:
def __init__(self, name):
self.name=name
@mydisplay
def display(self):
print(self.name)
s = Student("Srishti")
s.display()
Hello Srishti
Good Bye!
functools module
In [ ]: