unit 2 python
unit 2 python
What is Exception?
An exception is an event, which occurs during the execution of a program that disrupts the
normal flow of the program's instructions. In general, when a Python script encounters a situation
that it cannot cope with, it raises an exception. An exception is a Python object that represents an
error.
When a Python script raises an exception, it must either handle the exception immediately
otherwise it terminates and quits.
The above program is syntactically correct, but it through the error because of unusual input.
That kind of programming may not be suitable or recommended for the projects because these
projects are required uninterrupted execution. That's why an exception-handling plays an
essential role in handling these unexpected exceptions. We can handle these exceptions in the
following way.
Handling an exception
If you have some suspicious code that may raise an exception, you can defend your program by
placing the suspicious code in a try: block. After the try: block, include an except: statement,
followed by a block of code which handles the problem as elegantly as possible.
Syntax
Here is simple syntax of try....except...else blocks −
try:
You do your operations here;
......................
except ExceptionI:
If there is ExceptionI, then execute this block.
except ExceptionII:
If there is ExceptionII, then execute this block.
......................
▪ A single try statement can have multiple except statements. This is useful when the try
block contains statements that may throw different types of exceptions.
▪ You can also provide a generic except clause, which handles any exception.
Base class for all built-in exceptions except StopIteration and SystemExit.
5 ArithmeticError
Base class for all errors that occur for numeric calculation.
6 OverflowError
Raised when a calculation exceeds maximum limit for a numeric type.
7 FloatingPointError
Raised when a floating point calculation fails.
8 ZeroDivisionError
Raised when division or modulo by zero takes place for all numeric types.
9 AssertionError
Raised in case of failure of the Assert statement.
10 AttributeError
Raised in case of failure of attribute reference or assignment.
11 EOFError
Raised when there is no input from either the raw_input() or input() function and the
end of file is reached.
12 ImportError
Raised when an import statement fails.
13 KeyboardInterrupt
Raised when the user interrupts program execution, usually by pressing Ctrl+c.
14 LookupError
Base class for all lookup errors.
15 IndexError
Raised when an index is not found in a sequence
16 KeyError
Raised when the specified key is not found in the dictionary
17 NameError
Raised when an identifier is not found in the local or global namespace.
18 UnboundLocalError
Raised when trying to access a local variable in a function or method but no value
has been assigned to it.
19 EnvironmentError
Base class for all exceptions that occur outside the Python environment.
20 IOError
Raised when an input/ output operation fails, such as the print statement or the open()
function when trying to open a file that does not exist.
21 IOError
Raised for operating system-related errors.
22 SyntaxError
Raised when there is an error in Python syntax.
23 IndentationError
Raised when indentation is not specified properly.
24 SystemError
Raised when the interpreter finds an internal problem, but when this error is
encountered the Python interpreter does not exit.
25 SystemExit
Raised when Python interpreter is quit by using the sys.exit() function. If not handled
We can also use the else statement with the try-except statement in which, we can place the code
which will be executed in the scenario if no exception occurs in the try block.
Syntax:
try:
#block of code
except Exception1:
#block of code
else:
#this code executes if no except block is executed
Example
try:
a = int(input("Enter a:"))
b = int(input("Enter b:"))
c = a/b
print("a/b = %d"%c)
# Using Exception with except statement. If we print(Exception) it will return exception class
except Exception:
print("can't divide by zero")
print(Exception)
else:
print("Hi I am else block")
Output:
Enter a:10
Enter b:0
can't divide by zero
<class 'Exception'>
Points to remember
1. Python facilitates us to not specify the exception with the except statement.
2. We can declare multiple exceptions in the except statement since the try block may contain the
statements which throw
the different type of exceptions.
3. We can also specify an else block along with the try-except statement, which will be executed
if no exception is raised in
the try block.
4. The statements that don't throw the exception should be placed inside the else block.
Example
try:
#this will throw an exception if the file doesn't exist.
fileptr = open("file.txt","r")
except IOError:
print("File not found")
else:
print("The file opened successfully")
fileptr.close()
Output:
File not found
Example
try:
fh = open("testfile", "w")
try:
fh.write("This is my test file for exception handling!!")
finally:
print ("Going to close the file")
fh.close()
except IOError:
print ("Error: can\'t find file or read data")
When an exception is thrown in the try block, the execution immediately passes to
the finally block. After all the statements in the finally block are executed, the exception is raised
again and is handled in the exceptstatements if present in the next higher layer of the try-
except statement.
Argument of an Exception
Compiled by: Kruti Kotak, Christ College, Rajkot
CS:26 Programming in Python 8
An exception can have an argument, which is a value that gives additional information about the
problem. The contents of the argument vary by exception. You capture an exception's argument
by supplying a variable in the except clause as follows −
try:
You do your operations here;
......................
except ExceptionType as e:
You can print value of Argument here “e.args”...
If you write the code to handle a single exception, you can have a variable follow the name of the
exception in the except statement. If you are trapping multiple exceptions, you can have a
variable follow the tuple of the exception.
This variable receives the value of the exception mostly containing the cause of the exception.
The variable can receive a single value or multiple values in the form of a tuple. This tuple
usually contains the error string, the error number, and an error location.
Example
# Define a function here.
def temp_convert(var):
try:
return int(var)
except ValueError as ve:
print( "The argument does not contain numbers\n", ve.args)
Output
The argument does not contain numbers invalid literal for int() with base 10: 'xyz'
example2:
import sys
def tmp_cnv(var):
try:
return int(var)
except:
print("error in converting\n",sys.exc_info())
tmp_cnv("xy")
output:
error in converting
(<class 'ValueError'>, ValueError("invalid literal for int() with base 10: 'xy'"), <traceback object
at 0x038D2E68>)
Example3:
def tmp_cnv(var):
try:
return int(var)
except Exception as e:
print("error in converting:\n " + str(e))
# print(“error in converting:\n " + e.args)
tmp_cnv("xy")
Output:
error in converting:
("invalid literal for int() with base 10: 'xy'",)
Example4:
import traceback
def tmp_cnv(var):
try:
return int(var)
except:
print(traceback.format_exc())
tmp_cnv("xy")
output:
Traceback (most recent call last):
File "C:\Users\VAIBHAV\Desktop\e.py", line 4, in tmp_cnv
return int(var)
ValueError: invalid literal for int() with base 10: 'xy'
Raising an Exceptions
You can raise exceptions in several ways by using the raise statement. The general syntax for
the raise statement is as follows.
Syntax
raise [Exception [, args]]
Here, Exception is the type of exception (for example, NameError) and argument is a value for
the exception argument. The argument is optional; if not supplied, the exception argument is
None.
Example
try:
age = int(input("Enter the age:"))
if(age<18):
raise ValueError
else:
print("the age is valid")
except ValueError:
print("The age is not valid")
Output:
Enter the age:17
The age is not valid
Example 3
try:
a = int(input("Enter a:"))
b = int(input("Enter b:"))
if b is 0:
raise ArithmeticError
else:
print("a/b = ",a/b)
except ArithmeticError:
print("The value of b can't be 0")
Output:
Enter a:10
Enter b:0
The value of b can't be 0
assert <condition>
assert <condition>,<error message>
mark1 = []
print("Average of mark1:",avg(mark1))
We got an error as we passed an empty list mark1 to assert statement, the condition became false
and assert stops the program and give AssertionError.
Now let's pass another list which will satisfy the assert condition and see what will be our output.
mark2 = [55,88,78,90,79]
print("Average of mark2:",avg(mark2))
mark1 = []
print("Average of mark1:",avg(mark1))
We passed a non-empty list mark2 and also an empty list mark1 to the avg() function and we got
output for mark2 list but after that we got an error AssertionError: List is empty.
The assert condition was satisfied by the mark2 list and program to continue to run. However,
mark1 doesn't satisfy the condition and gives an AssertionError.
Class
A class is like a blueprint for building objects. Class is a programmer-defined data type, which
includes local functions as well as local data.
Object
Object is an individual instance of the data structure defined by a class. You define a class once
and then make many objects that belong to it. Objects are also known as instance.
Defining a class doesn't cause any objects to be created directly, it simply describes what an
instance of that class will look like when we do create it. A piece of code which belongs to
objects of a class is called a method.
Defining a class is straightforward, but first we must decide what instance variables and methods
it will have.
Creating Classes
The class statement creates a new class definition. The name of the class immediately follows the
keyword class followed by a colon as follows −
class ClassName:
'Optional class documentation string'
class_suite
The class has a documentation string, which can be accessed via ClassName.__doc__.
The class_suite consists of all the component statements defining class members, data attributes
and functions.
Example
Following is the example of a simple Python class −
class Employee:
'Common base class for all employees'
empCount = 0
def displayCount(self):
print ("Total Employee %d" % Employee.empCount)
def displayEmployee(self):
print ("Name : ", self.name, ", Salary: ", self.salary)
▪ The variable empCount is a class variable whose value is shared among all instances of a this
class. This can be accessed as Employee.empCount from inside the class or outside the class.
▪ The first method __init__() is a special method, which is called class constructor or
initialization method that Python calls when you create a new instance of this class.
▪ You declare other class methods like normal functions with the exception that the first
argument to each method is self. Python adds the self-argument to the list for you; you do not
need to include it when you call the methods.
Accessing Attributes
You access the object's attributes using the dot operator with object. Class variable would be
accessed using class name as follows −
emp1.displayEmployee()
emp2.displayEmployee()
def displayCount(self):
print ("Total Employee %d" % Employee.empCount)
def displayEmployee(self):
print ("Name : ", self.name, ", Salary: ", self.salary)
You can add, remove, or modify attributes of classes and objects at any time −
emp1.age = 7 # Add an 'age' attribute.
emp1.age = 8 # Modify 'age' attribute.
del emp1.age # Delete 'age' attribute.
Instead of using the normal statements to access attributes, you can use the following functions −
▪ The getattr(obj, name[, default]) − to access the attribute of object.
▪ The hasattr(obj,name) − to check if an attribute exists or not.
▪ The setattr(obj,name,value) − to set an attribute. If attribute does not exist, then it would
be created.
▪ The delattr(obj, name) − to delete an attribute.
Class Inheritance
Instead of starting from scratch, you can create a class by deriving it from a preexisting class by
listing the parent class in parentheses after the new class name.
The child class inherits the attributes of its parent class, and you can use those attributes as if
they were defined in the child class. A child class can also override data members and methods
from the parent.
Syntax
Derived classes are declared much like their parent class; however, a list of base classes to inherit
from is given after the class name −
class SubClassName (ParentClass1[, ParentClass2, ...]):
'Optional class documentation string'
class_suite
Example
class Parent: # define parent class
parentAttr = 100
def __init__(self):
print ("Calling parent constructor")
def parentMethod(self):
print ('Calling parent method')
def getAttr(self):
print ("Parent attribute :", Parent.parentAttr)
def childMethod(self):
print ('Calling child method')
Similar way, you can drive a class from multiple parent classes as follows −
class A: # define your class A
.....
You can use issubclass() or isinstance() functions to check a relationships of two classes and
instances.
issubclass()
The issubclass(sub, sup) boolean function returns true if the given subclass sub is indeed a
subclass of the superclass sup.
isinstance()
The isinstance(obj, Class) boolean function returns true if obj is an instance of class Class or is
an instance of a subclass of Class.
Abstraction in Python
Abstraction in Python is the process of hiding the real implementation of an application from the
user and emphasizing only on usage of it.
Example:
from abc import ABC
class Shape(ABC): #abstract class
def calculate_area(self): #abstract method
pass
class Rectangle(Shape):
length = 5
breadth = 3
def calculate_area(self):
return self.length * self.breadth
class Circle(Shape):
radius = 4
def calculate_area(self):
return 3.14 * self.radius * self.radius
Output:
Area of a rectangle: 15
Area of a circle: 50.24
Note:
An abstract class can have both a normal method and an abstract method
An abstract class cannot be instantiated, ie., we cannot create objects for the abstract class
class Rectangle(Shape):
length = 5
breadth = 3
def calculate_area(self):
return self.length * self.breadth
class Circle(Shape):
radius = 4
def calculate_area(self):
return 3.14 * self.radius * self.radius
Output:
I am a normal method defined inside the abstract class 'Shape'
Area of a rectangle: 15
Private members
Private class members should neither be accessed outside the class nor by any base class. In
Python, there is no existence of Private instance variables that cannot be accessed except inside
a class. However, to define a private member prefix the member name with double underscore
“__”.
Example 1
class Car:
def __init__(self):
self.__updateSoftware()
def drive(self):
print("Driving")
def __updateSoftware(self):
print("updating software")
redcar = Car()
redcar.drive()
#redcar.__updateSoftware() #not accesible from object.
Output:
updating software
Driving
Example 2
# Creating a Base class
class Base:
def __init__(self):
self.a = "Hello all"
self.__c = "Good morning"
# print(obj1.c)
# will raise an AttributeError
# obj2 = Derived()
# will also raise an AtrributeError as private member of base class is called inside derived class
Protected members
Protected members (in C++ and JAVA) are those members of the class that cannot be accessed outside the class
but can be accessed from within the class and its subclasses. To accomplish this in Python, just follow the
convention by prefixing the name of the member by a single underscore “_”.
Example
class Base:
def __init__(self):
# Protected member
self._a = 2
print(self._a)
obj1 = Derived()
obj2 = Base()
Linear Search
In this type of search, a sequential search is made over all items one by one. Every item is
checked and if a match is found then that particular item is returned, otherwise the search
continues till the end of the data structure.
def linear_search(values, search_for):
search_at = 0
search_res = False
return search_res
Binary search
Search a sorted array by repeatedly dividing the search interval in half. Begin with an interval
covering the whole array. If the value of the search key is less than the item in the middle of the
interval, narrow the interval to the lower half. Otherwise narrow it to the upper half. Repeatedly
check until the value is found or the interval is empty.
def binary_search(item_list,item):
first = 0
last = len(item_list)-1
found = False
while( first<=last and not found):
mid = (first + last)//2
if item_list[mid] == item :
found = True
else:
if item < item_list[mid]:
last = mid – 1
else:
first = mid + 1
return found
print(binary_search([1,2,3,5,8], 6))
print(binary_search([1,2,3,5,8], 5))
Insertion Sort
Insertion sort involves finding the right place for a given element in a sorted list. So in
beginning we compare the first two elements and sort them by comparing them. Then we pick
the third element and find its proper position among the previous two sorted elements. This way
we gradually go on adding more elements to the already sorted list by putting them in their
proper position.
def insertion_sort(InputList):
for i in range(1, len(InputList)):
j = i-1
nxt_element = InputList[i]
# Compare the current element with next one
while (InputList[j] > nxt_element) and (j >= 0):
InputList[j+1] = InputList[j]
j=j-1
InputList[j+1] = nxt_element
list = [19,2,31,45,30,11,121,27]
insertion_sort(list)
print(list)
When the above code is executed, it produces the following result −
[2, 11, 19, 27, 30, 31, 45, 121]
Merge Sort
Merge sort first divides the array into equal halves and then combines them in a sorted manner.
def merge_sort(unsorted_list):
if len(unsorted_list) <= 1:
return unsorted_list
# Find the middle point and devide it
middle = len(unsorted_list) // 2
left_list = unsorted_list[:middle]
right_list = unsorted_list[middle:]
left_list = merge_sort(left_list)
right_list = merge_sort(right_list)
return list(merge(left_list, right_list))
res = []
while len(left_half) != 0 and len(right_half) != 0:
if left_half[0] < right_half[0]:
res.append(left_half[0])
left_half.remove(left_half[0])
else:
res.append(right_half[0])
right_half.remove(right_half[0])
if len(left_half) == 0:
res = res + right_half
else:
res = res + left_half
return res
unsorted_list = [64, 34, 25, 12, 22, 11, 90]
print(merge_sort(unsorted_list))
When the above code is executed, it produces the following result −
[11, 12, 22, 25, 34, 64, 90]
Shell Sort
Shell Sort involves sorting elements which are away from ech other. We sort a large sublist of a
given list and go on reducing the size of the list until all elements are sorted. The below program
finds the gap by equating it to half of the length of the list size and then starts sorting all
elements in it. Then we keep resetting the gap until the entire list is sorted.
def shellSort(input_list):
gap = len(input_list) / / 2
while gap > 0:
for i in range(gap, len(input_list)):
temp = input_list[i]
j=i
# Sort the sub list for this gap
while j >= gap and input_list[j - gap] > temp:
input_list[j] = input_list[j - gap]
j = j-gap
input_list[j] = temp
# Reduce the gap for the next element
gap = gap//2
list = [19,2,31,45,30,11,121,27]
shellSort(list)
print(list)
Selection Sort
In selection sort we start by finding the minimum value in a given list and move it to a sorted
list. Then we repeat the process for each of the remaining elements in the unsorted list. The next
element entering the sorted list is compared with the existing elements and placed at its correct
position. So at the end all the elements from the unsorted list are sorted.
def selection_sort(input_list):
for idx in range(len(input_list)):
min_idx = idx
for j in range( idx +1, len(input_list)):
if input_list[min_idx] > input_list[j]:
min_idx = j
# Swap the minimum value with the compared value
input_list[idx], input_list[min_idx] = input_list[min_idx], input_list[idx]
l = [19,2,31,45,30,11,121,27]
selection_sort(l)
print(l)
When the above code is executed, it produces the following result −
[2, 11, 19, 27, 30, 31, 45, 121]
Updating Dictionary
You can update a dictionary by adding a new entry or a key-value pair, modifying an existing
entry, or deleting an existing entry as shown below in the simple example −
# Declare a dictionary
dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
dict['Age'] = 8; # update existing entry
dict['School'] = "DPS School"; # Add new entry
print ("dict['Age']: ", dict['Age'])
print ("dict['School']: ", dict['School'])
When the above code is executed, it produces the following result −
dict['Age']: 8
dict['School']: DPS School