You are on page 1of 219

Chapter 10

Python Implementation of OO
Programming
Declaration
 These slides are made for UIT, BU students only. I am not
holding any copy write of it as I had collected these study
materials from different books and websites etc. I have not
mentioned those to avoid complexity.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.2


Topics
 Class
 Object
 Instance and class attribute
 Inspecting and Overriding
 Function
 Decorator
 Lambda
 Inheritance
 Composition
 Module
 Package
 Testing
 Exception Handing

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.3


Python
Python is a multi-paradigm programming language, which means it
supports multiple programming paradigms, including:
 Object-Oriented Programming (OOP): Python allows you to
create and work with objects and classes, making it suitable for
building applications using OOP principles.
 Functional Programming: Python supports functional
programming concepts such as lambda functions, map, filter,
and reduce, which enable you to write code in a functional style.
 Procedural Programming: Python also supports procedural
programming, where you can write code in a structured, step-by-
step manner, similar to languages like C or Pascal.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.4


Python Classes/Objects
 Almost everything in Python is an object, with its properties and
methods.
 A Class is like an object constructor, or a "blueprint" for creating
objects. It is template of objects.
 Classes provide a means of bundling data and functionality
together.
 Creating a new class creates a new type of object, allowing new
instances of that type to be made.
 Each class instance can have attributes attached to it for
maintaining its state. Class instances can also have methods
(defined by their class) for modifying their state.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.5


Python Classes/Objects
 Class creates a user-defined data structure, which holds its own
data members and member functions, which can be accessed
and used by creating an instance of that class.
 Some points on Python class:
 Classes are created by keyword class.
 Attributes are the variables that belong to a class.
 Attributes are always public and can be accessed using the dot (.)
operator. Eg.: Myclass.Myattribute

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.6


Create a Class
 Example
Create a class named MyClass, with a property named x:
Code:
class MyClass:
x=5
print(MyClass)

You have to give “:” after the name of the class.

Output:
<class '__main__.MyClass'>

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.7


Class / Objects
 An Object is an instance of a Class. A class is like a blueprint
while an instance is a copy of the class with actual values.
 It‟s not an idea anymore, it‟s an actual dog, like a dog of breed
pug who‟s seven years old. You can have many dogs to create
many different instances, but without the class as a guide, you
would be lost, not knowing what information is required.
 An object consists of :
 State: It is represented by the attributes of an object. It also reflects
the properties of an object.
 Behavior: It is represented by the methods of an object. It also
reflects the response of an object to other objects.
 Identity: It gives a unique name to an object and enables one object
to interact with other objects.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.8


Class / Objects

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.9


Declaring Objects (Also called
instantiating a class)
 When an object of a class is created, the class is said to be
instantiated. All the instances share the attributes and the
behavior of the class. But the values of those attributes, i.e. the
state are unique for each object. A single class may have any
number of instances.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.10


Create Object
 Now we can use the class named MyClass to create objects:
 Example
Create an object named p1, and print the value of x:

Code:
p1 = MyClass()
print(p1.x)

Output:
5

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.11


The __init__() Function
 The examples above are classes and objects in their simplest
form, and are not really useful in real life applications.
 To understand the meaning of classes we have to understand
the built-in __init__() function.
 All classes have a function called __init__(), which is always
executed when the class is being initiated.
 Use the __init__() function to assign values to object properties,
or other operations that are necessary to do when the object is
being created:
 The __init__ method is similar to constructors in C++ and Java.
 The __init__() function is called automatically every time the
class is being used to create a new object.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.12


The __init__() Function
Example:
 Create a class named Person, use the __init__() function to
assign values for name and age:
Code:
class Person:
def __init__(self,name,age):
self.name = name
self.age = age

p1 = Person("John", 36)

print(p1.name)
print(p1.age)
Output:
John
36

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.13


Types of constructors
 default constructor: The default constructor is a simple
constructor which doesn‟t accept any arguments. Its definition
has only one argument which is a reference to the instance being
constructed.
 parameterized constructor: constructor with parameters is
known as parameterized constructor. The parameterized
constructor takes its first argument as a reference to the instance
being constructed known as self and the rest of the arguments
are provided by the programmer.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.14


Object Methods
 Objects can also contain methods. Methods in objects are
functions that belong to the object.
 Let us create a method in the Person class:
 Example
Code:
class Person:
#2 “_” at both sides of init
def __init__(self, name, age):
self.name = name
self.age = age

def myfunc(self):
print("Hello my name is " + self.name)

p1 = Person("John", 36)
p1.myfunc()
Output:
Hello my name is John
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.15
The self Parameter
 The self parameter is a reference to the current instance of the
class, and is used to access variables that belongs to the class.
 It does not have to be named self, you can call it whatever you
like, but it has to be the first parameter of any function in the
class:
 Example
Code:
Use the words mysillyobject and abc instead of self:
class Person:
def __init__(mysillyobject, name, age):
mysillyobject.name = name
mysillyobject.age = age

def myfunc(abc):
print("Hello my name is " + abc.name)

p1 = Person("John", 36)
p1.myfunc()
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.16
Class and Instance Variables
 Instance variables are for data, unique to each instance and
 Class variables are for attributes and methods shared by all
instances of the class.
 Instance variables are variables whose value is assigned inside
a constructor or method with self
 Whereas class variables are variables whose value is assigned
in the class.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.17


Class and Instance Variables
class Dog:
# Class Variable
animal = 'dog'
# The init method or constructor
def __init__(self, breed, color):
# Instance Variable
self.breed = breed
self.color = color
# Objects of Dog class
Rodger = Dog("Pug", "brown")
Buzo = Dog("Bulldog", "black")

print('Rodger details:')
print('Rodger is a', Rodger.animal)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.18


Class and Instance Variables
print('Breed: ', Rodger.breed)
print('Color: ', Rodger.color)

print('\nBuzo details:')
print('Buzo is a', Buzo.animal)
print('Breed: ', Buzo.breed)
print('Color: ', Buzo.color)

# Class variables can be accessed using class


# name also
print("\nAccessing class variable using class name")
print(Dog.animal)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.19


Class and Instance Variables
 Output:
Rodger details:
Rodger is a dog
Breed: Pug
Color: brown
Buzo details: Buzo is a dog
Breed: Bull dog
Color: black
Accessing class variable using class name
dog

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.20


Method Overriding
 Method overriding is an ability of any object-oriented
programming language that allows a subclass or child class to
provide a specific implementation of a method that is already
provided by one of its super-classes or parent classes. When a
method in a subclass has the same name, same parameters or
signature and same return type (or sub-type) as a method in its
super-class, then the method in the subclass is said
to override the method in the super-class.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.21


Method Overriding

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.22


Method Overriding
 The version of a method that is executed will be determined by
the object that is used to invoke it. If an object of a parent class is
used to invoke the method, then the version in the parent class
will be executed, but if an object of the subclass is used to invoke
the method, then the version in the child class will be executed.
In other words, it is the type of the object being referred to (not
the type of the reference variable) that determines which version
of an overridden method will be executed.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.23


Method Overriding
# Python program to demonstrate method overriding

# Defining parent class


class Parent():

# Constructor
def __init__(self):
self.value = "Inside Parent"

# Parent's show method


def show(self):
print(self.value)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.24


Method Overriding
# Defining child class
class Child(Parent):

# Constructor
def __init__(self):
self.value = "Inside Child"

# Child's show method


def show(self):
print(self.value)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.25


Method Overriding
# Driver's code
obj1 = Parent()
obj2 = Child()

obj1.show()
obj2.show()

Output:
Inside Parent
Inside Child

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.26


Method Overriding
Multiple Inheritance: When a class is derived from more than one
base class it is called multiple Inheritance.
Example: Let‟s consider an example where we want to override a
method of one parent class only. Below is the implementation.

# Python program to demonstrate overriding in multiple inheritance

# Defining parent class 1


class Parent1():

# Parent's show method


def show(self):
print("Inside Parent1")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.27


Method Overriding
# Defining Parent class 2
class Parent2():

# Parent's show method


def display(self):
print("Inside Parent2")

# Defining child class


class Child(Parent1, Parent2):

# Child's show method


def show(self):
print("Inside Child")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.28


Method Overriding
# Driver's code
obj = Child()

obj.show()
obj.display()

Output:
Inside Child
Inside Parent2

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.29


Method Overriding
 Multilevel Inheritance: When we have a child and grandchild
relationship.
 Example: Let‟s consider an example where we want to override
only one method of one of its parent classes. Below is the
implementation.

# Python program to demonstrate overriding in multilevel inheritance

class Parent():

# Parent's show method


def display(self):
print("Inside Parent")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.30


Method Overriding
# Inherited or Sub class (Note Parent in bracket)
class Child(Parent):

# Child's show method


def show(self):
print("Inside Child")

# Inherited or Sub class (Note Child in bracket)


class GrandChild(Child):

# Child's show method


def show(self):
print("Inside GrandChild")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.31


Method Overriding
# Driver code
g = GrandChild()
g.show()
g.display()

Output:
Inside GrandChild
Inside Parent

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.32


Method Overriding
 Calling the Parent’s method within the overridden method
 Parent class methods can also be called within the overridden
methods. This can generally be achieved by two ways.
 Using Classname: Parent‟s class methods can be called by
using the Parent classname.method inside the overridden
method.
 Example:
# Python program to demonstrate calling the parent's class method
inside the overridden method
class Parent():

def show(self):
print("Inside Parent")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.33


Method Overriding
class Child(Parent):

def show(self):

# Calling the parent's class method


Parent.show(self)
print("Inside Child")

# Driver's code
obj = Child()
obj.show()

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.34


Method Overriding
Output:
Inside Parent
Inside Child

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.35


Method Overriding
 Using Super(): Python super() function provides us the facility to
refer to the parent class explicitly. It is basically useful where we
have to call superclass functions. It returns the proxy object that
allows us to refer parent class by „super‟.

# Python program to demonstrate calling the parent's class method inside


the overridden method using super()

class Parent():

def show(self):
print("Inside Parent")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.36


Method Overriding
class Child(Parent):

def show(self):

# Calling the parent's class


# method
super().show()
print("Inside Child")

# Driver's code
obj = Child()
obj.show()

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.37


Method Overriding
 Output:
Inside Parent
Inside Child

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.38


Functions
 A function is a block of code which only runs when it is called.
 You can pass data, known as parameters, into a function.
 A function can return data as a result.
 Creating a Function: In Python a function is defined using
the def keyword:

def my_function():
print("Hello from a function")

 Calling a Function: To call a function, use the function name followed


by parenthesis

my_function()

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.39


Functions
 Arguments: Information can be passed into functions as
arguments.
 Arguments are specified after the function name, inside the
parentheses. You can add as many arguments as you want, just
separate them with a comma.
 The following example has a function with one argument
(fname). When the function is called, we pass along a first name,
which is used inside the function to print the full name:
def my_function(fname):
print(" Hello“+ fname)

my_function(“RAM")
my_function(“SAM")
my_function(“JODU")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.40


Functions
 Parameters or Arguments?
The terms parameter and argument can be used for the same thing:
information that are passed into a function.
 From a function's perspective:
 A parameter is the variable listed inside the parentheses in the
function definition.
 An argument is the value that is sent to the function when it is
called.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.41


Functions
 Arbitrary Arguments, *args
 If you do not know how many arguments that will be passed into
your function, add a * before the parameter name in the function
definition.
 This way the function will receive a tuple of arguments, and can
access the items accordingly:
def my_function(*kids):
print("The youngest child is " + kids[2])

my_function(“RAM", “SAM", “JODU")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.42


Functions
Keyword Arguments
 You can also send arguments with the key = value syntax.
 This way the order of the arguments does not matter.
def my_function(child3, child2, child1):
print("The youngest child is " + child3)

my_function(child1 = “RAM", child2 = “SAM", child3 = “JADU")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.43


Functions
Arbitrary Keyword Arguments, **kwargs
 If you do not know how many keyword arguments that will be
passed into your function, add two asterisk: ** before the
parameter name in the function definition.
 This way the function will receive a dictionary of arguments, and
can access the items accordingly:
def my_function(**kid):
print("His last name is " + kid["lname"])

my_function(fname = “NIKHIL", lname = “CHOPRA")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.44


Functions
Default Parameter Value
 The following example shows how to use a default parameter
value.
 If we call the function without argument, it uses the default value:

def my_function(country = "Norway"):


print("I am from " + country)

my_function("Sweden")
my_function("India")
my_function()
my_function("Brazil")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.45


Functions
Passing a List as an Argument
 You can send any data types of argument to a function (string,
number, list, dictionary etc.), and it will be treated as the same
data type inside the function.
 E.g. if you send a List as an argument, it will still be a List when it
reaches the function:

def my_function(food):
for x in food:
print(x)

fruits = ["apple", "banana", "cherry"]

my_function(fruits)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.46


Functions
Return Values
 To let a function return a value, use the return statement:
def my_function(x):
return 5 * x

print(my_function(3))
print(my_function(5))
print(my_function(9))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.47


Functions
The pass Statement
 Function definitions cannot be empty, but if you for some reason
have a function definition with no content, put in
the pass statement to avoid getting an error.
def myfunction():
pass

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.48


Functions
Recursion
 Python also accepts function recursion, which means a defined
function can call itself.

def tri_recursion(k):
if(k > 0):
result = k + tri_recursion(k - 1)
print(result)
else:
result = 0
return result

print("\n\nRecursion Example Results")


tri_recursion(6)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.49


Decorators
 Decorators are a very powerful and useful tool in Python since it
allows programmers to modify the behaviour of a function or
class. Decorators allow us to wrap another function in order to
extend the behaviour of the wrapped function, without
permanently modifying it.
 But before diving deep into decorators let us understand some
concepts that will come in handy in learning the decorators.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.50


Decorators
 First Class Objects: In Python, functions are first class
objects which means that functions in Python can be used
or passed as arguments. Properties of first class functions:
 A function is an instance of the Object type.
 You can store the function in a variable.
 You can pass the function as a parameter to another function.
 You can return the function from a function.
 You can store them in data structures such as hash tables, lists, …

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.51


Functions
 Example 1: Treating the functions as objects.
# Python program to illustrate functions can be treated as objects
def shout(text):
return text.upper()

print(shout('Hello'))

yell = shout

print(yell('Hello'))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.52


Functions
 Output:
HELLO
HELLO

 In the above example, we have assigned the function shout to a


variable. This will not call the function instead it takes the
function object referenced by a shout and creates a second
name pointing to it, yell.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.53


Functions
 Example 2: Passing the function as an argument
# Python program to illustrate functions can be passed as arguments to
other functions
def shout(text):
return text.upper()
def whisper(text):
return text.lower()
def greet(func):
# storing the function in a variable
greeting = func("""Hi, I am created by a function passed as an
argument.""")
print (greeting)
greet(shout)
greet(whisper)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.54


Functions
 Output:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT.
hi, i am created by a function passed as an argument.
 In the above example, the greet function takes another function
as a parameter (shout and whisper in this case). The function
passed as an argument is then called inside the function greet.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.55


Functions
 Example 3: Returning functions from another function.
# Python program to illustrate functions
# Functions can return another function

def create_adder(x):
def adder(y):
return x+y

return adder

add_15 = create_adder(15)

print(add_15(10))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.56


Functions
 Output:
25

 In the above example, we have created a function inside of


another function and then have returned the function created
inside.
 The code defines a Python function called create_adder that
takes an argument x. This function returns another function,
adder, which takes an argument y and returns the sum of x and
y. In essence, it creates a closure where x is "captured" by the
adder function, allowing you to use it even after create_adder
has finished executing.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.57


Decorators
 Decorator can modify the behavior of functions or methods
without changing their source code:
# defining a decorator
def hello_decorator(func):
# inner1 is a Wrapper function in which the argument is called
# inner function can access the outer local functions like in this case
"func"
def inner1():
print("Hello, this is before function execution")
# calling the actual function now inside the wrapper function.
func()
print("This is after function execution")
return inner1

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.58


Decorators
# defining a function, to be called inside wrapper
def function_to_be_used():
print("This is inside the function !!")

# passing 'function_to_be_used' inside the decorator to control its behaviour


function_to_be_used = hello_decorator(function_to_be_used)

# calling the function


function_to_be_used()

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.59


Decorators
 Output:
Hello, this is before function execution
This is inside the function !!
This is after function execution

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.60


Decorators
 def hello_decorator(func): defines a decorator function called
hello_decorator, which takes another function func as its
argument. Decorators are functions that wrap or modify other
functions.
 Inside the hello_decorator function, there is a nested function
called inner1. This nested function will act as a wrapper around
the original func that you pass to the decorator.
 Inside inner1, you can see some print statements. These
statements are executed before and after calling the original
function func. So, inner1 is effectively adding some behavior
before and after the execution of func.
 return inner1 returns the inner1 function as the result of calling
hello_decorator(func). This means that when you decorate a
function with hello_decorator, you get back the inner1 function,
which wraps the original function.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.61


Decorators
 def function_to_be_used(): defines a regular Python function called
function_to_be_used. This function is what you want to modify or
decorate.
 function_to_be_used = hello_decorator(function_to_be_used) decorates
the function_to_be_used function by passing it to the hello_decorator.
Now, function_to_be_used is reassigned to the inner1 function returned
by hello_decorator. This means that when you call
function_to_be_used, you're actually calling the decorated version.
 Finally, function_to_be_used() is called. When you call it, it actually
executes the inner1 function (the decorated version), which prints
"Hello, this is before function execution," then calls the original
function_to_be_used, which prints "This is inside the function !!," and
then prints "This is after function execution.“

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.62


Decorators
# importing libraries
import time
import math
# decorator to calculate duration taken by any function.
def calculate_time(func):
# added arguments inside the inner1, if function takes any arguments,
can be added like this.
def inner1(*args, **kwargs):
# storing time before function execution
begin = time.time()
func(*args, **kwargs)
# storing time after function execution
end = time.time()
print("Total time taken in : ", func.__name__, end - begin)
return inner1
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.63
Decorators
# this can be added to any function present,
# in this case to calculate a factorial
@calculate_time
def factorial(num):

# sleep 2 seconds because it takes very less time


# so that you can see the actual difference
time.sleep(2)
print(math.factorial(num))

# calling the function.


factorial(10)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.64


Decorators
 Output:
3628800
Total time taken in : factorial 2.0061802864074707

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.65


Decorators
 What if a function returns something or an argument is
passed to the function?
 In all the above examples the functions didn‟t return anything so
there wasn‟t an issue, but one may need the returned value.

def hello_decorator(func):
def inner1(*args, **kwargs):
print("before Execution")
# getting the returned value
returned_value = func(*args, **kwargs)
print("after Execution")
# returning the value to the original frame
return returned_value
return inner1

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.66


Decorators
# adding decorator to the function
@hello_decorator
def sum_two_numbers(a, b):
print("Inside the function")
return a + b
a, b = 1, 2
# getting the value through return of the function
print("Sum =", sum_two_numbers(a, b))
Output:
before Execution
Inside the function
after Execution
Sum = 3

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.67


Decorators
 In the above example, you may notice a keen difference in the
parameters of the inner function. The inner function takes the
argument as *args and **kwargs which means that a tuple of
positional arguments or a dictionary of keyword arguments can
be passed of any length. This makes it a general decorator that
can decorate a function having any number of arguments.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.68


Decorators
 Chaining Decorators: In simpler terms chaining
decorators means decorating a function with multiple decorators.
# code for testing decorator chaining
def decor1(func):
def inner():
x = func()
return x * x
return inner

def decor(func):
def inner():
x = func()
return 2 * x
return inner

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.69


Decorators
@decor1
@decor
def num():
return 10

print(num())

Output:
400

The above example is similar to calling the function as –


decor1(decor(num))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.70


Lambda
 Python Lambda Functions are anonymous function means that
the function is without a name.
 As we already know that the def keyword is used to define a
normal function in Python.
 Similarly, the lambda keyword is used to define an anonymous
function in Python.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.71


Lambda
 Python Lambda Function Syntax
 Syntax: lambda arguments: expression
 This function can have any number of arguments but only one
expression, which is evaluated and returned.
 One is free to use lambda functions wherever function objects are
required.
 You need to keep in your knowledge that lambda functions are
syntactically restricted to a single expression.
 It has various uses in particular fields of programming, besides other
types of expressions in functions.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.72


Lambda
str1 = „Uit'

# lambda returns a function object


rev_upper = lambda string: string.upper()[::-1]
print(rev_upper(str1))

Output:
TIU

Explanation: In the above example, we defined a lambda


function(rev_upper) to convert a string to it‟s upper-case and
reverse it.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.73


Lambda
 Difference Between Lambda functions and def defined
function
def cube(y):
return y*y*y

lambda_cube = lambda y: y*y*y

# using function defined using def keyword


print("Using function defined with `def` keyword, cube:", cube(5))

# using the lambda function


print("Using lambda function, cube:", lambda_cube(5))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.74


Lambda
 Output:
Using function defined with `def` keyword, cube: 125
Using lambda function, cube: 125

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.75


Lambda
With lambda function Without lambda function
Supports single line statements that Supports any number of lines inside
returns some value. a function block

Good for performing short Good for any cases that require
operations/data manipulations. multiple lines of code.

Using lambda function can We can use comments and function


sometime reduce the readability of descriptions for easy readability.
code.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.76


Lambda
 Python Lambda Function with List Comprehension

is_even_list = [lambda arg=x: arg * 10 for x in range(1, 5)]

# iterate on each lambda function


# and invoke the function to get the calculated value
for item in is_even_list:
print(item())
Output:
10
20
30
40

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.77


Lambda
 Explanation: On each iteration inside the list comprehension,
we are creating a new lambda function with default argument of x
(where x is the current item in the iteration). Later, inside the for
loop, we are calling the same function object having the default
argument using item() and getting the desired value.
Thus, is_even_list stores the list of lambda function objects.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.78


Lambda
 Python Lambda Function with if-else
# Example of lambda function using if-else
Max = lambda a, b : a if(a > b) else b

print(Max(1, 2))

Output:
2

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.79


Lambda
 Using lambda() Function with filter()
Filter out all odd numbers using filter() and lambda function
li = [5, 7, 22, 97, 54, 62, 77, 23, 73, 61]

final_list = list(filter(lambda x: (x % 2 != 0), li))


print(final_list)

Output:
[5, 7, 97, 77, 23, 73, 61]

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.80


Lambda
 Using lambda() Function with map()
 The map() function in Python takes in a function and a list as an
argument. The function is called with a lambda function and a list
and a new list is returned which contains all the lambda modified
items returned by that function for each item.
 Example:
Multiply all elements of a list by 2 using lambda and map()
function
# Python code to illustrate
# map() with lambda()
# to get double of a list.
li = [5, 7, 22, 97, 54, 62, 77, 23, 73, 61]

final_list = list(map(lambda x: x*2, li))


print(final_list)
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.81
Lambda
 Output:
[10, 14, 44, 194, 108, 124, 154, 46, 146, 122]

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.82


Lambda
 Using lambda() Function with reduce()
 The reduce() function in Python takes in a function and a list as
an argument. The function is called with a lambda function and
an iterable and a new reduced result is returned. This performs a
repetitive operation over the pairs of the iterable. The reduce()
function belongs to the functools module.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.83


Lambda
 Sum of all elements in a list using lambda and reduce()
function
# Python code to illustrate
# reduce() with lambda()
# to get sum of a list

from functools import reduce


li = [5, 8, 10, 20, 50, 100]
sum = reduce((lambda x, y: x + y), li)
print(sum)

Output:
193

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.84


Lambda
 Find the maximum element in a list using lambda and
reduce() function
# python code to demonstrate working of reduce() with a lambda function

# importing functools for reduce()


import functools

# initializing list
lis = [1, 3, 5, 6, 2, ]

# using reduce to compute maximum element from list


print("The maximum element of the list is : ", end="")
print(functools.reduce(lambda a, b: a if a > b else b, lis))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.85


Inheritance
 Inheritance is the capability of one class to derive or inherit the
properties from another class.
 Benefits of inheritance are:
 It represents real-world relationships well.
 It provides the reusability of a code. We don‟t have to write the
same code again and again. Also, it allows us to add more features
to a class without modifying it.
 It is transitive in nature, which means that if class B inherits from
another class A, then all the subclasses of B would automatically
inherit from class A.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.86


Inheritance
 Python Inheritance Syntax
Class BaseClass:
{Body}
Class DerivedClass(BaseClass):
{Body}

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.87


Inheritance
 Creating a Parent Class
class Person(object):
# Constructor
def __init__(self, name, id):
self.name = name
self.id = id
# To check if this person is an employee
def Display(self):
print(self.name, self.id)
# Driver code
emp = Person("Satyam", 102) # An Object of Person
emp.Display()

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.88


Inheritance
 Output:
Satyam 102

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.89


Inheritance
 Creating a Child Class
class Emp(Person):

def Print(self):
print("Emp class called")

Emp_details = Emp("Mayank", 103)

# calling parent class function


Emp_details.Display()

# Calling child class function


Emp_details.Print()

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.90


Inheritance
 Output:
Mayank 103
Emp class called

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.91


Inheritance
 Example of Inheritance in Python
# A Python program to demonstrate inheritance

# Base or Super class. Note object in bracket.


# (Generally, object is made ancestor of all classes)
# In Python 3.x "class Person" is
# equivalent to "class Person(object)"

class Person(object):
# Constructor
def __init__(self, name):
self.name = name

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.92


Inheritance
# To get name
def getName(self):
return self.name
# To check if this person is an employee
def isEmployee(self):
return False

# Inherited or Subclass (Note Person in bracket)


class Employee(Person):

# Here we return true


def isEmployee(self):
return True

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.93


Inheritance
# Driver code
emp = Person(“UIT1") # An Object of Person
print(emp.getName(), emp.isEmployee())

emp = Employee(“UIT2") # An Object of Employee


print(emp.getName(), emp.isEmployee())

Output:
UIT1 False
UIT2 True

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.94


Inheritance
 What is object class?
 Like the Java Object class, in Python (from version 3. x), the object
is the root of all classes.
 In Python 3.x, “class Test(object)” and “class Test” are same.
 In Python 2. x, “class Test(object)” creates a class with the object as
a parent (called a new-style class), and “class Test” creates an old-
style class (without an objecting parent).
 Subclassing (Calling constructor of parent class)
 A child class needs to identify which class is its parent class. This
can be done by mentioning the parent class name in the definition of
the child class.
 Eg: class subclass_name (superclass_name):

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.95


Inheritance
# Python code to demonstrate how parent constructors
# are called.

# parent class
class Person(object):

# __init__ is known as the constructor


def __init__(self, name, idnumber):
self.name = name
self.idnumber = idnumber

def display(self):
print(self.name)
print(self.idnumber)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.96


Inheritance
# child class
class Employee(Person):
def __init__(self, name, idnumber, salary, post):
self.salary = salary
self.post = post

# invoking the __init__ of the parent class


Person.__init__(self, name, idnumber)

# creation of an object variable or an instance


a = Employee('Rahul', 886012, 200000, "Intern")

# calling a function of the class Person using its instance


a.display()

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.97


Inheritance
 Output:
Rahul
886012

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.98


Inheritance
 „a‟ is the instance created for the class Person. It invokes the
__init__() of the referred class. You can see „object‟ written in the
declaration of the class Person. In Python, every class inherits
from a built-in basic class called „object‟. The constructor i.e. the
„__init__‟ function of a class is invoked when we create an object
variable or an instance of the class.
 The variables defined within __init__() are called the instance
variables or objects. Hence, „name‟ and „idnumber‟ are the
objects of the class Person. Similarly, „salary‟ and „post‟ are the
objects of the class Employee. Since the class Employee inherits
from class Person, „name‟ and „idnumber‟ are also the objects of
class Employee.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.99


Inheritance
 Python program to demonstrate error if we forget to invoke
__init__() of the parent
 If you forget to invoke the __init__() of the parent class then its instance
variables would not be available to the child class.
 The following code produces an error for the same reason.
class A:
def __init__(self, n='Rahul'):
self.name = n

class B(A):
def __init__(self, roll):
self.roll = roll

object = B(23)
print(object.name)
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.100
Inheritance
 Output :
Traceback (most recent call last):
File "/home/de4570cca20263ac2c4149f435dba22c.py", line 12, in
print (object.name)
AttributeError: 'B' object has no attribute 'name'

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.101


Different types of Inheritance
 Different types of Inheritance:
 Single inheritance: When a child class inherits from only one
parent class, it is called single inheritance. We saw an example
above.
 Multiple inheritances: When a child class inherits from multiple
parent classes, it is called multiple inheritances. Unlike java, python
shows multiple inheritances.
 Multilevel inheritance: When we have a child and grandchild
relationship.
 Hierarchical inheritance More than one derived class are created
from a single base.
 Hybrid inheritance: This form combines more than one form of
inheritance. Basically, it is a blend of more than one type of
inheritance.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.102


Different types of Inheritance

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.103


Different types of Inheritance

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.104


Different types of Inheritance

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.105


Different types of Inheritance

Hybrid Inheritance

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.106


Different types of Inheritance

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.107


Multiple Inheritance
# Python example to show the working of multiple
# inheritance

class Base1(object):
def __init__(self):
self.str1 = “UIT1"
print("Base1")

class Base2(object):
def __init__(self):
self.str2 = “UIT2"
print("Base2")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.108


Multiple Inheritance
class Derived(Base1, Base2):
def __init__(self):

# Calling constructors of Base1


# and Base2 classes
Base1.__init__(self)
Base2.__init__(self)
print("Derived")

def printStrs(self):
print(self.str1, self.str2)

ob = Derived()
ob.printStrs()

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.109


Multiple Inheritance
 Output:
Base1
Base2
Derived
UIT1 UIT2

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.110


Multilevel Inheritance
# A Python program to demonstrate inheritance

# Base or Super class. Note object in bracket.


# (Generally, object is made ancestor of all classes)
# In Python 3.x "class Person" is
# equivalent to "class Person(object)"
class Base(object):
# Constructor
def __init__(self, name):
self.name = name
# To get name
def getName(self):
return self.name

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.111


Multilevel Inheritance
# Inherited or Sub class (Note Person in bracket)
class Child(Base):

# Constructor
def __init__(self, name, age):
Base.__init__(self, name)
self.age = age

# To get name
def getAge(self):
return self.age

# Inherited or Sub class (Note Person in bracket)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.112


Multilevel Inheritance
class GrandChild(Child):

# Constructor
def __init__(self, name, age, address):
Child.__init__(self, name, age)
self.address = address

# To get address
def getAddress(self):
return self.address

# Driver code
g = GrandChild(“UIT1", 23, “Burdwan")
print(g.getName(), g.getAge(), g.getAddress())

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.113


Multilevel Inheritance
Output:
UIT1 23 Burdwan

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.114


Inheritance
 Private members of the parent class
 We don‟t always want the instance variables of the parent class
to be inherited by the child class i.e. we can make some of the
instance variables of the parent class private, which won‟t be
available to the child class.
 We can make an instance variable private by adding double
underscores before its name. For example,
# Python program to demonstrate private members
# of the parent class
class C(object):
def __init__(self):
self.c = 21

# d is private instance variable


self.__d = 42
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.115
Inheritance
class D(C):
def __init__(self):
self.e = 84
C.__init__(self)

object1 = D()

# produces an error as d is private instance variable


print(object1.d)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.116


Multiple Inheritance
 Output :
File "/home/993bb61c3e76cda5bb67bd9ea05956a1.py", line 16, in
print (object1.d)
AttributeError: type object 'D' has no attribute 'd'

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.117


Inheritance
 Is-A Relation
 It is a concept of Object-Oriented Programming. Inheritance is a
mechanism that allows us to inherit all the properties from
another class. The class from which the properties and
functionalities are utilized is called the parent class (also called
as Base Class). The class which uses the properties from
another class is called as Child Class (also known as Derived
class). Inheritance is also called an Is-A Relation.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.118


Composition
 Has-A Relation
 It is one of the fundamental concepts of Object-
Oriented Programming. In this concept, we will describe a class
that references to one or more objects of other classes as an
Instance variable. Here, by using the class name or by creating
the object we can access the members of one class inside
another class. It enables creating complex types by combining
objects of different classes. It means that a class Composite can
contain an object of another class Component. This type of
relationship is known as Has-A Relation.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.119


Composition

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.120


Composition
class A :
# variables of class A
# methods of class A
...
...
class B :
# by using "obj" we can access member's of class A.
obj = A()
# variables of class B
# methods of class B

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.121


Composition
class Component:
# composite class constructor
def __init__(self):
print('Component class object created...')
# composite class instance method
def m1(self):
print('Component class m1() method executed...')

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.122


Composition
class Composite:
# composite class constructor
def __init__(self):
# creating object of component class
self.obj1 = Component()
print('Composite class object also created...')
# composite class instance method
def m2(self):
print('Composite class m2() method executed...')
# calling m1() method of component class
self.obj1.m1()

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.123


Composition
# creating object of composite class
obj2 = Composite()
# calling m2() method of composite class
obj2.m2()

Output:
Component class object created...
Composite class object also created...
Composite class m2() method executed...
Component class m1() method executed...

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.124


Composition
 Explanation:
 In the above example, we created two
classes Composite and Component to show the Has-A
Relation among them.
 In the Component class, we have one constructor and an
instance method m1().
 Similarly, in Composite class, we have one constructor in which
we created an object of Component Class. Whenever we create
an object of Composite Class, the object of the Component
class is automatically created.
 Now in m2() method of Composite class we are
calling m1() method of Component Class using instance
variable obj1 in which reference of Component Class is stored.
 Now, whenever we call m2() method of Composite
Class, automatically m1() method of Component Class will be
called.
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.125
Python Modules
 A Python module is a file containing Python definitions and
statements. A module can define functions, classes, and
variables. A module can also include runnable code. Grouping
related code into a module makes the code easier to understand
and use. It also makes the code logically organized.
 Example: create a simple module
# A simple module, calc.py

def add(x, y):


return (x+y)

def subtract(x, y):


return (x-y)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.126


Import Module in Python – Import
statement
 We can import the functions, classes defined in a module to
another module using the import statement in some other
Python source file.

 Syntax:
import module

 When the interpreter encounters an import statement, it imports


the module if the module is present in the search path. A search
path is a list of directories that the interpreter searches for
importing a module. For example, to import the module calc.py,
we need to put the following command at the top of the script.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.127


Import Module in Python – Import
statement
 Note: This does not import the functions or classes directly
instead imports the module only. To access the functions inside
the module the dot(.) operator is used.
# importing module calc.py
import calc

print(calc.add(10, 2))

Output:
12

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.128


The from import Statement
 Python‟s from statement lets you import specific attributes from a
module without importing the module as a whole.
 Example: Importing specific attributes from the module
# importing sqrt() and factorial from the
# module math
from math import sqrt, factorial

# if we simply do "import math", then


# math.sqrt(16) and math.factorial()
# are required.
print(sqrt(16))
print(factorial(6))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.129


The from import Statement
 Output:
4.0
720

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.130


Import all Names – From import
* Statement
 The * symbol used with the from import statement is used to
import all the names from a module to a current namespace.
 Syntax:
from module_name import *
 The use of * has its advantages and disadvantages. If you know
exactly what you will be needing from the module, it is not
recommended to use *, else do so.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.131


Import all Names – From import
* Statement
 Example: Importing all names

# importing sqrt() and factorial from the


# module math
from math import *

# if we simply do "import math", then


# math.sqrt(16) and math.factorial()
# are required.
print(sqrt(16))
print(factorial(6))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.132


Import all Names – From import
* Statement
 Output
4.0
720

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.133


Locating Modules
 Whenever a module is imported in Python the interpreter looks
for several locations. First, it will check for the built-in module, if
not found then it looks for a list of directories defined in the
sys.path. Python interpreter searches for the module in the
following manner –
 First, it searches for the module in the current directory.
 If the module isn‟t found in the current directory, Python then
searches each directory in the shell variable PYTHONPATH. The
PYTHONPATH is an environment variable, consisting of a list of
directories.
 If that also fails python checks the installation-dependent list of
directories configured at the time Python is installed.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.134


Locating Modules
 Example: Directories List for Modules
# importing sys module
import sys

# importing sys.path
print(sys.path)
 Output:
[‘/home/nikhil/Desktop/gfg’, ‘/usr/lib/python38.zip’, ‘/usr/lib/python3.8’,
‘/usr/lib/python3.8/lib-dynload’, ”, ‘/home/nikhil/.local/lib/python3.8/site-
packages’, ‘/usr/local/lib/python3.8/dist-packages’, ‘/usr/lib/python3/dist-
packages’, ‘/usr/local/lib/python3.8/dist-packages/IPython/extensions’,
‘/home/nikhil/.ipython’]

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.135


Importing and renaming module
 We can rename the module while importing it using the as
keyword.
 Example: Renaming the module
# importing sqrt() and factorial from the
# module math
import math as gfg

# if we simply do "import math", then


# math.sqrt(16) and math.factorial()
# are required.
print(gfg.sqrt(16))
print(gfg.factorial(6))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.136


The dir() function
 The dir() built-in function returns a sorted list of strings containing
the names defined by a module. The list contains the names of
all the modules, variables, and functions that are defined in a
module.
# Import built-in module random
import random
print(dir(random))
 Output:
 [‘BPF’, ‘LOG4’, ‘NV_MAGICCONST’, ‘RECIP_BPF’, ‘Random’,
‘SG_MAGICCONST’, ‘SystemRandom’, ‘TWOPI’, ‘_BuiltinMethodType’,
‘_MethodType’, ‘_Sequence’, ‘_Set’, ‘__all__’, ‘__builtins__’, ‘__cached__’,
‘__doc__’, ‘__file__’, ‘__loader__’, ‘__name__’, ‘__package__’, ‘__spec__’,
‘_acos’, ‘_bisect’, ‘_ceil’, ‘_cos’, ‘_e’, ‘_exp’, ‘_inst’, ‘_itertools’, ‘_log’, ‘_pi’,
‘_random’, ‘_sha512’, ‘_sin’, ‘_sqrt’, ‘_test’, ‘_test_generator’, ‘_urandom’, ‘_warn’,
‘betavariate’, ‘choice’, ‘choices’, ‘expovariate’, ‘gammavariate’, ‘gauss’,
‘getrandbits’, ‘getstate’, ‘lognormvariate’, ‘normalvariate’, ‘paretovariate’, ‘randint’,
‘random’, ‘randrange’, ‘sample’, ‘seed’, ‘setstate’, ‘shuffle’, ‘triangular’, ‘uniform’,
‘vonmisesvariate’, ‘weibullvariate’]

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.137


python built-in modules
# importing built-in module math
import math

# using square root(sqrt) function contained


# in math module
print(math.sqrt(25))

# using pi function contained in math module


print(math.pi)

# 2 radians = 114.59 degrees


print(math.degrees(2))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.138


python built-in modules
# 60 degrees = 1.04 radians
print(math.radians(60))

# Sine of 2 radians
print(math.sin(2))

# Cosine of 0.5 radians


print(math.cos(0.5))

# Tangent of 0.23 radians


print(math.tan(0.23))

# 1 * 2 * 3 * 4 = 24
print(math.factorial(4))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.139


python built-in modules
 Output:
5.0
3.14159265359
114.591559026
1.0471975512
0.909297426826
0.87758256189
0.234143362351
24

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.140


python built-in modules
# importing built in module random
import random

# printing random integer between 0 and 5


print(random.randint(0, 5))

# print random floating point number between 0 and 1


print(random.random())

# random number between 0 and 100


print(random.random() * 100)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.141


python built-in modules
List = [1, 4, True, 800, "python", 27, "hello"]

# using choice function in random module for choosing


# a random element from a set such as a list
print(random.choice(List))

Output:
3
0.401533172951
88.4917616788
True

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.142


python built-in modules
# importing built in module datetime
import datetime
from datetime import date
import time

# Returns the number of seconds since the


# Unix Epoch, January 1st 1970
print(time.time())

# Converts a number of seconds to a date object


print(date.fromtimestamp(454554))

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.143


python built-in modules
Output:
1461425771.87

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.144


Python Packages
 We usually organize our files in different folders and subfolders
based on some criteria, so that they can be managed easily and
efficiently. For example, we keep all our games in a Games
folder and we can even subcategorize according to the genre of
the game or something like this. The same analogy is followed
by the Python package.
 A Python module may contain several classes, functions,
variables, etc. whereas a Python package can contains several
module. In simpler terms a package is folder that contains
various modules as files.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.145


Creating Package

 Let‟s create a package named mypckg that will contain two


modules mod1 and mod2. To create this package follow the below
steps –
 Create a folder named mypckg.
 Inside this folder create an empty Python file i.e. __init__.py
 Then create two modules mod1 and mod2 in this folder.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.146


Creating Package

 Mod1.py
def gfg():
print("Welcome to GFG")

 Mod2.py
def sum(a, b):
return a+b

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.147


Creating Package

 The hierarchy of the our package looks like this –


Mypckg
|
|
---
__init__.py
|
|
---mod1.py
|
|
---mod2.py

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.148


Understanding __init__.py
 __init__.py helps the Python interpreter to recognize the folder
as package. It also specifies the resources to be imported from
the modules. If the __init__.py is empty this means that all the
functions of the modules will be imported. We can also specify
the functions from each module to be made available.
 For example, we can also create the __init__.py file for the
above module as –
 __init__.py
from .mod1 import gfg
from .mod2 import sum
 This __init__.py will only allow the gfg and sum functions from
the mod1 and mod2 modules to be imported.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.149


Import Modules from a Package
 We can import these modules using the from…import
statement and the dot(.) operator.
 Syntax:
import package_name.module_name
 Example: Import Module from package
 We will import the modules from the above created package and
will use the functions inside those modules.
from mypckg import mod1
from mypckg import mod2

mod1.gfg()
res = mod2.sum(1, 2)
print(res)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.150


Import Modules from a Package

 Output:
Welcome to GFG
3

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.151


Import Modules from a Package

 We can also import the specific function also using the same
syntax.
 Example: Import Specific function from the module
from mypckg.mod1 import gfg
from mypckg.mod2 import sum

gfg()
res = sum(1, 2)
print(res)
 Output:
Welcome to GFG
3

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.152


Testing
 Testing in Python is a huge topic and can come with a lot of
complexity, but it doesn‟t need to be hard.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.153


Automated vs. Manual Testing
 The good news is, you‟ve probably already created a test
without realizing it. Remember when you ran your application
and used it for the first time? Did you check the features and
experiment using them? That‟s known as exploratory
testing and is a form of manual testing.
 Exploratory testing is a form of testing that is done without a
plan. In an exploratory test, you‟re just exploring the application.
 To have a complete set of manual tests, all you need to do is
make a list of all the features your application has, the different
types of input it can accept, and the expected results. Now,
every time you make a change to your code, you need to go
through every single item on that list and check it.
 That doesn‟t sound like much fun, does it?

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.154


Automated vs. Manual Testing
 This is where automated testing comes in. Automated testing is
the execution of your test plan (the parts of your application you
want to test, the order in which you want to test them, and the
expected responses) by a script instead of a human. Python
already comes with a set of tools and libraries to help you create
automated tests for your application.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.155


Unit Tests vs. Integration Tests
 Think of how you might test the lights on a car. You would turn
on the lights (known as the test step) and go outside the car or
ask a friend to check that the lights are on (known as the test
assertion). Testing multiple components is known
as integration testing.
 Think of all the things that need to work correctly in order for a
simple task to give the right result. These components are like
the parts to your application, all of those classes, functions, and
modules you‟ve written.
 A major challenge with integration testing is when an integration
test doesn‟t give the right result. It‟s very hard to diagnose the
issue without being able to isolate which part of the system is
failing. If the lights didn‟t turn on, then maybe the bulbs are
broken. Is the battery dead? What about the alternator? Is the
car‟s computer failing?

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.156


Unit Tests vs. Integration Tests
 If you have a fancy modern car, it will tell you when your light
bulbs have gone. It does this using a form of unit test.
 A unit test is a smaller test, one that checks that a single
component operates in the right way. A unit test helps you to
isolate what is broken in your application and fix it faster.
 You have just seen two types of tests:
 An integration test checks that components in your application
operate with each other.
 A unit test checks a small component in your application.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.157


Test Driven Development
 Testing is so important to good software development that
there‟s even a software development process based on testing,
Test Driven Development (TDD).
 The key idea of TDD is that we base our software development
around a set of unit tests that we have created, which makes unit
testing the heart of the TDD software development process. This
way, you are assured that you have a test for every component
you develop.
 TDD is also biased toward having smaller tests which means
tests that are more specific and test fewer components at a time.
This aids in tracking down errors, and smaller tests are also
easier to read and understand since there are fewer components
at play in a single run.
 It doesn‟t mean you must use TDD for your projects. But you
may consider that as a method to develop your code and the
tests at the same time.
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.158
Unit Test
 You can write both integration tests and unit tests in Python. To
write a unit test for the built-in function sum(), you would check
the output of sum() against a known output.
 For example, here‟s how you check that the sum() of the
numbers (1, 2, 3) equals 6:
assert sum([1, 2, 3]) == 6, "Should be 6“
 This will not output anything because the values are correct.
 If the result from sum() is incorrect, this will fail with
an AssertionError and the message "Should be 6".
assert sum([1, 1, 1]) == 6, "Should be 6"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: Should be 6
 In the output, you are seeing the raised AssertionError because
the result of sum() does not match 6.
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.159
Unit Test

 You can put this into a new Python file called test_sum.py and
execute it again:
def test_sum():
assert sum([1, 2, 3]) == 6, "Should be 6"
if __name__ == "__main__":
test_sum()
print("Everything passed")
 Now you have written a test case, an assertion, and an entry
point (the command line). You can now execute this at the
command line:

$ python test_sum.py
Everything passed

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.160


Unit Test
 In Python, sum() accepts any iterable as its first argument. You
tested with a list. Now test with a tuple as well. Create a new file
called test_sum_2.py with the following code:
def test_sum():
assert sum([1, 2, 3]) == 6, "Should be 6"
def test_sum_tuple():
assert sum((1, 2, 2)) == 6, "Should be 6"
if __name__ == "__main__":
test_sum()
test_sum_tuple()
print("Everything passed")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.161


Unit Test
 When you execute test_sum_2.py, the script will give an error
because the sum() of (1, 2, 2) is 5, not 6. The result of the script
gives you the error message, the line of code, and the traceback:
$ python test_sum_2.py
Traceback (most recent call last):
File "test_sum_2.py", line 9, in <module>
test_sum_tuple()
File "test_sum_2.py", line 5, in test_sum_tuple
assert sum((1, 2, 2)) == 6, "Should be 6"
AssertionError: Should be 6

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.162


Unit Test
 Writing tests in this way is okay for a simple check, but what if
more than one fails? This is where test runners come in. The test
runner is a special application designed for running tests,
checking the output, and giving you tools for debugging and
diagnosing tests and applications.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.163


Test Runner
 There are many test runners available for Python. The one built
into the Python standard library is called unittest. In this tutorial,
you will be using unittest test cases and the unittest test runner.
The principles of unittest are easily portable to other frameworks.
The three most popular test runners are:
 unittest
 nose or nose2
 pytest
 Choosing the best test runner for your requirements and level of
experience is important.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.164


Test Runner
1 class Rectangle:
2 def __init__(self, width, height):
3 self.width = width
4 self.height = height
5
6 def get_area(self):
7 return self.width * self.height
8
9 def set_width(self, width):
1 self.width = width
0
1 def set_height(self, height):
1 self.height = height
1
2
1
3

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.165


unittest
 To get started building a test file, we need to import
the unittest library
import unittest
 Unit tests in PyUnit are structured as subclasses of
the unittest.TestCase class, and we can override
the runTest() method to perform our own unit tests which check
conditions using different assert functions in unittest.TestCase:

1 class TestGetAreaRectangle(unittest.TestCase):
2 def runTest(self):
3 rectangle = Rectangle(2, 3)
4 self.assertEqual(rectangle.get_area(), 6, "incorrect area")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.166


unittest
 To run the unit test, we make a call to unittest.main() in our
program,

1 ...
2 unittest.main()

 Since the code returns the expected output for this case, it
returns that the tests run successfully, with the output:

1 .
2 ----------------------------------------------------------------------
3 Ran 1 test in 0.003s
4
5 OK

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.167


unittest
The complete code is as follows:
import unittest
# Our code to be tested
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height

def get_area(self):
return self.width * self.height

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.168


unittest
def set_width(self, width):
self.width = width

def set_height(self, height):


self.height = height

# The test based on unittest module


class TestGetAreaRectangle(unittest.TestCase):
def runTest(self):
rectangle = Rectangle(2, 3)
self.assertEqual(rectangle.get_area(), 6, "incorrect area")

# run the test


unittest.main()
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.169
unittest
 We can also nest multiple unit tests together in one subclass
of unittest.TestCase, by naming methods in the new subclass
with the “test” prefix, for example:

1 class TestGetAreaRectangle(unittest.TestCase):
2 def test_normal_case(self):
3 rectangle = Rectangle(2, 3)
4 self.assertEqual(rectangle.get_area(), 6, "incorrect area")
5
6 def test_negative_case(self):
7 """expect -1 as output to denote error when looking at
8 negative area"""
9 rectangle = Rectangle(-1, 2)
self.assertEqual(rectangle.get_area(), -1, "incorrect
negative output")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.170


unittest
1 F.
2 =================================================
3 =====================
4 FAIL: test_negative_case (__main__.TestGetAreaRectangle)
5 expect -1 as output to denote error when looking at negative
6 area
7 ----------------------------------------------------------------------
8 Traceback (most recent call last):
9 File "<ipython-input-96-59b1047bb08a>", line 9, in
1 test_negative_case
0 self.assertEqual(rectangle.get_area(), -1, "incorrect negative
1 output")
1 AssertionError: -2 != -1 : incorrect negative output
1 ----------------------------------------------------------------------
2 Ran 2 tests in 0.003s
1
3 FAILED (failures=1)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.171


PyTest
 PyTest is an alternative to the built-in unittest module.
 To get started with PyTest, you will first need to install it, which
you can do using:

1 pip install pytest

 Shell
To write tests, you just need to write functions with names
prefixed with “test,” and PyTest‟s test discovery procedure will be
able to find your tests, e.g.,

1 def test_normal_case(self):
2 rectangle = Rectangle(2, 3)
3 assert rectangle.get_area() == 6, "incorrect area"

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.172


PyTest
 You will notice that PyTest uses Python‟s built-in assert keyword
instead of its own set of assert functions as PyUnit does, which
might make it slightly more convenient since we can avoid
searching for the different assert functions.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.173


PyTest
1 # Our code to be tested
2 class Rectangle:
3 def __init__(self, width, height):
4 self.width = width
5 self.height = height
6
7 def get_area(self):
8 return self.width * self.height
9
10 def set_width(self, width):
11 self.width = width
12
13 def set_height(self, height):
14 self.height = height
15
16 # The test function to be executed by PyTest
17 def test_normal_case():
18 rectangle = Rectangle(2, 3)
19 assert rectangle.get_area() == 6, "incorrect area"

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.174


PyTest
 After saving this into a file test_file.py, we can run PyTest unit
test by:

1 python -m pytest test_file.py

 And this gives us the output:


Shell

1 =================== test session starts


2 ====================
3 platform darwin -- Python 3.9.9, pytest-7.0.1, pluggy-1.0.0
4 rootdir: /Users/MLM
5 plugins: anyio-3.4.0, typeguard-2.13.2
6 collected 1 item
7
8 test_file.py . [100%]
9
==================== 1 passed in 0.01s
=====================
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.175
First Test
 Let‟s bring together what you‟ve learned so far and, instead of
testing the built-in sum() function, test a simple implementation of
the same requirement.
 Create a new project folder and, inside that, create a new folder
called my_sum. Inside my_sum, create an empty file
called __init__.py. Creating the __init__.py file means that
the my_sum folder can be imported as a module from the parent
directory.
 Your project folder should look like this:
project/

└── my_sum/
└── __init__.py

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.176


First Test
 Open up my_sum/__init__.py and create a new function
called sum(), which takes an iterable (a list, tuple, or set) and
adds the values together:
def sum(arg):
total = 0
for val in arg:
total += val
return total
 This code example creates a variable called total, iterates over
all the values in arg, and adds them to total. It then returns the
result once the iterable has been exhausted.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.177


First Test
 To get started writing tests, you can simply create a file
called test.py, which will contain your first test case. Because the
file will need to be able to import your application to be able to
test it, you want to place test.py above the package folder, so
your directory tree will look something like this:

project/

├── my_sum/
│ └── __init__.py
|
└── test.py

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.178


How to Structure a Simple Test
 Before you dive into writing tests, you‟ll want to first make a
couple of decisions:
 What do you want to test?
 Are you writing a unit test or an integration test?
 Then the structure of a test should loosely follow this workflow:
 Create your inputs
 Execute the code being tested, capturing the output
 Compare the output with an expected result

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.179


How to Structure a Simple Test
 For this application, you‟re testing sum(). There are many
behaviors in sum() you could check, such as:
 Can it sum a list of whole numbers (integers)?
 Can it sum a tuple or set?
 Can it sum a list of floats?
 What happens when you provide it with a bad value, such as a
single integer or a string?
 What happens when one of the values is negative?

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.180


How to Structure a Simple Test
 The most simple test would be a list of integers. Create a
file, test.py with the following Python code:
import unittest
from my_sum import sum
class TestSum(unittest.TestCase):
def test_list_int(self):
"""
Test that it can sum a list of integers
"""
data = [1, 2, 3]
result = sum(data)
self.assertEqual(result, 6)
if __name__ == '__main__':
unittest.main()

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.181


Assertions
Method Equivalent to
.assertEqual(a, b) a == b
.assertTrue(x) bool(x) is True
.assertFalse(x) bool(x) is False
.assertIs(a, b) a is b
.assertIsNone(x) x is None
.assertIn(a, b) a in b
.assertIsInstance(a, b) isinstance(a, b)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.182


Integration Tests
 Integration testing is the testing of multiple components of the
application to check that they work together. Integration testing
might require acting like a consumer or user of the application
by:
 Calling an HTTP REST API
 Calling a Python API
 Calling a web service
 Running a command line
 Each of these types of integration tests can be written in the
same way as a unit test, following the Input, Execute, and Assert
pattern. The most significant difference is that integration tests
are checking more components at once and therefore will have
more side effects than a unit test. Also, integration tests will
require more fixtures to be in place, like a database, a network
socket, or a configuration file.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.183


Integration Tests
 This is why it‟s good practice to separate your unit tests and your
integration tests. The creation of fixtures required for an
integration like a test database and the test cases themselves
often take a lot longer to execute than unit tests, so you may only
want to run integration tests before you push to production
instead of once on every commit.
 A simple way to separate unit and integration tests is simply to
put them in different folders:

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.184


Integration Tests
project/

├── my_app/
│ └── __init__.py

└── tests/
|
├── unit/
| ├── __init__.py
| └── test_sum.py
|
└── integration/
├── __init__.py
└── test_integration.py

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.185


Conclusion
 Python has made testing accessible by building in the
commands and libraries you need to validate that your
applications work as designed. Getting started with testing in
Python needn‟t be complicated: you can use unittest and write
small, maintainable methods to validate your code.
 As you learn more about testing and your application grows, you
can consider switching to one of the other test frameworks,
like pytest, and start to leverage more advanced features.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.186


Types of errors
 Error in Python can be of two types i.e. Syntax errors and
Exceptions.
 Errors are the problems in a program due to which the program
will stop the execution. “Syntax Error” - As the name suggests
this error is caused by the wrong syntax in the code.
 Exceptions are raised when the program is syntactically correct,
but the code resulted in an error. This error does not stop the
execution of the program, however, it changes the normal flow
of the program.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.187


Exception handling
# initialize the amount variable
marks = 10000

# perform division with 0


a = marks / 0
print(a)

Output:

In the above example raised the ZeroDivisionError as we are trying to


divide a number by 0.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.188


Keywords for Exception handling
 The try block lets you test a block of code for errors.
 The except block lets you handle the error.
 The else block lets you execute code when there is no error.
 The finally block lets you execute code, regardless of the result
of the try- and except blocks.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.189


Try and Except Statement – Catching
Exceptions
 Try and except statements are used to catch and handle
exceptions in Python. Statements that can raise exceptions are
kept inside the try clause and the statements that handle the
exception are written inside except clause.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.190


Try and Except Statement – Catching
Exceptions
 The try block will generate an exception, because x is not
defined:
try:
print(x)
except:
print("An exception occurred")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.191


Try and Except Statement – Catching
Exceptions
# Python program to handle simple runtime error
#Python 3

a = [1, 2, 3]
try:
print ("Second element = %d" %(a[1]))

# Throws error since there are only 3 elements in array


print ("Fourth element = %d" %(a[3]))

except:
print ("An error occurred")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.192


Try and Except Statement – Catching
Exceptions
 Output:
Second element = 2
An error occurred

In the above example, the statements that can cause the error are
placed inside the try statement (second print statement in our case).
The second print statement tries to access the fourth element of the
list which is not there and this throws an exception. This exception
is then caught by the except statement.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.193


Catching Specific Exception
 A try statement can have more than one except clause, to
specify handlers for different exceptions. Please note that at
most one handler will be executed. For example, we can add
IndexError in the above code. The general syntax for adding
specific exceptions are –
try:
# statement(s)
except IndexError:
# statement(s)
except ValueError:
# statement(s)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.194


Catching Specific Exception
try:
print(x)
except NameError:
print("Variable x is not defined")
except:
print("Something else went wrong")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.195


Catching Specific Exception
# Program to handle multiple errors with one
# except statement
# Python 3

def fun(a):
if a < 4:

# throws ZeroDivisionError for a = 3


b = a/(a-3)

# throws NameError if a >= 4


print("Value of b = ", b)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.196


Catching Specific Exception
try:
fun(3)
fun(5)

# note that braces () are necessary here for


# multiple exceptions
except ZeroDivisionError:
print("ZeroDivisionError Occurred and Handled")
except NameError:
print("NameError Occurred and Handled")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.197


Catching Specific Exception
 Output:
ZeroDivisionError Occurred and Handled
If you comment on the line fun(3), the output will be
NameError Occurred and Handled
The output above is so because as soon as python tries to access
the value of b, NameError occurs.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.198


Try with Else Clause
 In python, you can also use the else clause on the try-except
block which must be present after all the except clauses. The
code enters the else block only if the try clause does not raise an
exception.

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.199


Try with Else Clause
try:
print("Hello")
except:
print("Something went wrong")
else:
print("Nothing went wrong")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.200


Try with Else Clause
# Program to depict else clause with try-except
# Python 3
# Function which returns a/b
def AbyB(a , b):
try:
c = ((a+b) / (a-b))
except ZeroDivisionError:
print ("a/b result in 0")
else:
print (c)

# Driver program to test above function


AbyB(2.0, 3.0)
AbyB(3.0, 3.0)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.201


Try with Else Clause
Output:
-5.0
a/b result in 0

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.202


Finally
 Python provides a keyword finally, which is always executed
after the try and except blocks. The final block always executes
after normal termination of try block or after try block terminates
due to some exception.
 Syntax:
try:
# Some Code....
except:
# optional block
# Handling of exception (if required)
else:
# execute if no exception
finally:
# Some code .....(always executed)

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.203


Finally
try:
print(x)
except:
print("Something went wrong")
finally:
print("The 'try except' is finished")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.204


Finally
try:
f = open("demofile.txt")
try:
f.write("Lorum Ipsum")
except:
print("Something went wrong when writing to the file")
finally:
f.close()
except:
print("Something went wrong when opening the file")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.205


Finally
# Python program to demonstrate finally
# No exception Exception raised in try block
try:
k = 5//0 # raises divide by zero exception.
print(k)
# handles zerodivision exception
except ZeroDivisionError:
print("Can't divide by zero")
finally:
# this block is always executed
# regardless of exception generation.
print('This is always executed')

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.206


Finally

 Output:
Can't divide by zero
This is always executed

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.207


Raising Exception

 The raise statement allows the programmer to force a specific


exception to occur. The sole argument in raise indicates the
exception to be raised. This must be either an exception instance
or an exception class (a class that derives from Exception).

# Program to depict Raising Exception


try:
raise NameError("Hi there") # Raise Error
except NameError:
print ("An exception")
raise # To determine whether the exception was raised or not

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.208


Raising Exception

 The output of the above code will simply line printed as “An
exception” but a Runtime error will also occur in the last due to
the raise statement in the last line. So, the output on your
command line will look like
Traceback (most recent call last):
File "/home/d6ec14ca595b97bff8d8034bbf212a9f.py", line 5, in
<module>
raise NameError("Hi there") # Raise Error
NameError: Hi there
An exception

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.209


Raising Exception
x = -1

if x < 0:
raise Exception("Sorry, no numbers below zero")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.210


Raising Exception
x = "hello"

if not type(x) is int:


raise TypeError("Only integers are allowed")

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.211


How try() works?

 First, the try clause is executed i.e. the code


between try and except clause.
 If there is no exception, then only the try clause will
run, except the clause is finished.
 If any exception occurs, the try clause will be skipped
and except clause will run.
 If any exception occurs, but the except clause within the code
doesn‟t handle it, it is passed on to the outer try statements. If
the exception is left unhandled, then the execution stops.
 A try statement can have more than one except clause

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.212


How try() works?

 Code 1: No exception, so the try clause will run.


# Python code to illustrate
# working of try()
def divide(x, y):
try:
# Floor Division : Gives only Fractional Part as Answer
result = x // y
print("Yeah ! Your answer is :", result)
except ZeroDivisionError:
print("Sorry ! You are dividing by zero ")
# Look at parameters and note the working of Program
divide(3, 2)
Output :
'Yeah ! Your answer is :', 1

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.213


How try() works?

 Code 2: There is an exception so only except clause will run.


# Python code to illustrate
# working of try()
def divide(x, y):
try:
# Floor Division : Gives only Fractional Part as Answer
result = x // y
print("Yeah ! Your answer is :", result)
except ZeroDivisionError:
print("Sorry ! You are dividing by zero ")
# Look at parameters and note the working of Program
divide(3, 0)
Output :
Sorry ! You are dividing by zero

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.214


Built-in Exceptions
1. exception BaseException: This is the base class for all built-in
exceptions.
2. exception Exception
This is the base class for all built-in non-system-exiting
exceptions. All user-defined exceptions should also be derived
from this class.
3. exception ArithmeticError
This class is the base class for those built-in exceptions that are
raised for various arithmetic errors such as :
 OverflowError
 ZeroDivisionError
 FloatingPointError

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.215


Built-in Exceptions
4. exception BufferError
This exception is raised when buffer related operations cannot be
performed.
5. exception LookupError
This is the base class for those exceptions that are raised when a
key or index used on a mapping or sequence is invalid or not found.
The exceptions raised are :
 KeyError
 IndexError
try:
a = [1, 2, 3]
print (a[3])
except LookupError:
print ("Index out of bound error.")
else:
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.216
User-defined Exceptions
 Exceptions need to be derived from the Exception class, either
directly or indirectly. Although not mandatory, most of the
exceptions are named as names that end in “Error” similar to
the naming of the standard exceptions in python.
# A python program to create user-defined exception
# class MyError is derived from super class Exception
class MyError(Exception):

# Constructor or Initializer
def __init__(self, value):
self.value = value

# __str__ is to print() the value


def __str__(self):
return(repr(self.value))
11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.217
User-defined Exceptions
try:
raise(MyError(3*2))

# Value of Exception is stored in error


except MyError as error:
print('A New Exception occurred: ', error.value)

Output:
'A New Exception occurred: ', 6

11/17/2023 11:47 PM Dr. Dipankar Dutta, UIT, BU 1.218


End of Chapter 10

Questions?

You might also like