0% found this document useful (0 votes)
2 views

Functional Programming

The document discusses Functional Programming, highlighting its principles, advantages, and comparison with Object-Oriented Programming. It covers key concepts such as list comprehensions, closures, and decorators in Python, providing examples of their usage. The document emphasizes the efficiency and reusability of functional programming techniques in coding.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Functional Programming

The document discusses Functional Programming, highlighting its principles, advantages, and comparison with Object-Oriented Programming. It covers key concepts such as list comprehensions, closures, and decorators in Python, providing examples of their usage. The document emphasizes the efficiency and reusability of functional programming techniques in coding.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

5/24/22, 9:54 PM Functional Programming

UNIT-III: Functional Programming

Course Outcome

localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 1/14


5/24/22, 9:54 PM Functional Programming

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

Advantages of Functional Programming

localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 2/14


5/24/22, 9:54 PM Functional Programming

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.

Comparison between FP & OOPS

localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 3/14


5/24/22, 9:54 PM Functional Programming

localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 4/14


5/24/22, 9:54 PM Functional Programming

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.

The general syntax of list comprehensions is

[expr for element in iterable if condition]

localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 5/14


5/24/22, 9:54 PM Functional Programming

Above is equivalent to
for element in iterable:
if condition:
expr

List Comprehension vs For Loop

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 vs lambda function

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)

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 6/14


5/24/22, 9:54 PM Functional Programming

In [11]: lst1 = [x**2 for x in lst]


print(lst1)

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

List comprehensions with conditional expression

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)

[4, 16, 36, 64, 100]

Nested if with List Comprehension

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]

if...else with List Comprehension

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']

Nested Loop vs Nested List Comphrehension

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)

[[1, 4], [2, 5], [3, 6], [4, 8]]

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)

[[1, 3, 5, 7], [2, 4, 6, 8]]

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)

[[4, 6, 8], [5, 7, 6]]

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)

[[4, 6, 8], [5, 7, 6]]

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)

Python Dictionary Comprehension

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

{key: value for var in iterable}


Code to generate numbers as keys and their squares as values within the range of 10.

In [9]:
# creating the dictionary
squares = {i: i ** 2 for i in range(10)}
print(squares)

{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

Code to create a dictionary from [a, b, c, d] and [1, 2, 3, 4].

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)

{'a': 1, 'b': 2, 'c': 3, 'd': 4}

Python Set Comprehension

Set comprehensions are pretty similar to list comprehensions.


The only difference between them is that set comprehensions use curly brackets { }.

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)

Set using for loop: {2, 4, 6}

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)

Set using set comprehensions: {2, 4, 6}

localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 9/14


5/24/22, 9:54 PM Functional Programming

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.

These three conditions must be met:

It must have a nested function.


This nested function must refer to a variable nonlocal to it (a variable in the scope enclosing it).

localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 10/14


5/24/22, 9:54 PM Functional Programming

The enclosing scope must return this function.

Benefits of Python Closure

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

@newdesign # Decorating the olddesign using newdesign


def olddesign():
print("Old details")
olddesign()

++++++++++++++++
Old details
++++++++++++++++

In [27]:
print(olddesign.__name__)

inner

Decorating function with arguments.


In [28]:
def designAdd(fun):
def inner(a,b):
print("SUM = ",end="")
return fun(a,b)
return inner

@designAdd # add = designAdd(add)


def add(x,y):
return x + y

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)

localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 12/14


5/24/22, 9:54 PM Functional Programming

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

Nested decorators (Chaining decorator or multiple decorator)


In [30]:
# Example : Program to convert the message into list of uppercase strings
def upper_dec(func):
def wrapper():
s1 = func()
return s1.upper()
return wrapper
def split_dec(func):
def inner():
s2 = func()
return s2.split()
return inner

@split_dec
@upper_dec
def myfun():
return "Hello Students"
myfun()

['HELLO', 'STUDENTS']
Out[30]:

Decorator function with argument


In [31]:
def outer(msg):
def upper_dec(func):
def inner():
return func() + msg
return inner
return upper_dec
localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 13/14
5/24/22, 9:54 PM Functional Programming

@outer("! Welcome to the world of programming")


def myfun():
return "Hello Students"
#myfun=outer("Good")(myfun)
print(myfun())

Hello Students! Welcome to the world of programming

In [32]:
myfun.__name__

'inner'
Out[32]:

Decorating instance method


In [33]:
def mydisplay(fun):
def inner(name_ref):
print("Hello",end=" ")
fun(name_ref)
print("Good Bye!")
return inner

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 [ ]:

localhost:8888/nbconvert/html/Functional Programming.ipynb?download=false 14/14

You might also like