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

OO Python-Module 2 (1)

The document covers key object-oriented programming concepts in Python, focusing on inheritance, polymorphism, and exception handling. It explains various types of inheritance, method overloading, and overriding, along with their advantages and practical examples. Additionally, it discusses method resolution order and duck typing, emphasizing Python's dynamic typing capabilities.

Uploaded by

ashutosh.wk.24
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

OO Python-Module 2 (1)

The document covers key object-oriented programming concepts in Python, focusing on inheritance, polymorphism, and exception handling. It explains various types of inheritance, method overloading, and overriding, along with their advantages and practical examples. Additionally, it discusses method resolution order and duck typing, emphasizing Python's dynamic typing capabilities.

Uploaded by

ashutosh.wk.24
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 30

Mastering Object-Oriented Concepts in

Python

1|Page
Module 2: Python Inheritance, Polymorphism & Exception Handling
Types on inheritance, Single Inheritance, Multiple Inheritance, Method overloading and Method Overriding,
Method Resolution Order(MRO), Duck Typing Philosophy of Python Abstract method and Abstract Class,
Interfaces in Python - Compile time errors, Runtime Errors, Logical Errors, Exception, Exception handling,
Types of Exception.

Polymorphism and Inheritance in Python

Inheritance permits new classes to inherit features from existing classes, decreasing redundancy and
reusing code. Polymorphism lets objects of diverse types share the same interface, empowering methods to
be executed unexpectedly based on the object type. This decreases the code required and streamlines
upkeep.

What is Inheritance in Python

Inheritance could be a feature of object-oriented programming that permits one class to acquire
characteristics from another class. In other words, inheritance permits a class to be characterized in terms of
another class, which makes it simpler to make and keep up an application.

What is Polymorphism in Python

Polymorphism allows objects of different types to be treated similarly. In other words, polymorphism
allows objects to be treated as a single type of object, even if they are of different types. This means that a
single set of code can handle any object, even if the objects are of different types.

Advantages of Inheritance and Polymorphism

Inheritance:

 It permits code to be reused and avoids code duplication.


 It permits for the creation of hierarchical classifications.
 It permits for extensibility, as new subclasses can be made.
 It permits for less demanding support and debugging.

Polymorphism:

 It permits for the execution of dynamic dispatch and the implementation of interfaces.
 It reduces the number of lines of code and makes it simpler to maintain.
 It permits for the execution of more generic algorithms.
 It permits the execution of more adaptable programs.

18 | P a g e
Types of Inheritance in Python

 Single inheritance: A derived class inherits from one base class.


 Multiple inheritance: A derived class inherits from multiple base classes.
 Multilevel inheritance: A derived class inherits from a base class that inherits from another base class.
 Hierarchical inheritance: Multiple derived classes inherit from the same base class.
 Hybrid inheritance: A combination of two or more of the above inheritance types.

Syntax to create a derived class is −

In object-oriented terminology when class X extend class Y, then Y is called super class or base class
and X is called subclass or derived class. One more point to note that only data fields and method which are
not private are accessible by child classes, private data fields and methods are accessible only inside the
class.

Syntax to create a subclass is:

class SubClass(SuperClass):

# data fields

# instance methods

class Vehicle:

def __init__(self, name, color):


self.__name = name # __name is private to Vehicle class
self.__color = color

def getColor(self): # getColor() function is accessible to class Car


return self.__color

def setColor(self, color): # setColor is accessible outside the class


self.__color = color

def getName(self): # getName() is accessible outside the class


return self.__name

class Car(Vehicle):

def __init__(self, name, color, model):


# call parent constructor to set name and color
super().__init__(name, color)
self.__model = model

def getDescription(self):
return self.getName() + self.__model + " in " + self.getColor() + " color"

# in method getDescrition we are able to call getName(), getColor() because they are
# accessible to child class through inheritance

19 | P a g e
c = Car("Ford Mustang", "red", "GT350")
print(c.getDescription())
print(c.getName()) # car has no method getName() but it is accessible via class Vehicle

Output:

Ford MustangGT350 in red color


Ford Mustang
Here we have created base class Vehicle and it's subclass Car. Notice that we have not
defined getName() in the Car class but we are still able to access it, because the class Car inherits it from
the Vehicle class. In the above code super() method is used to call method of the base class. Here is the
how super() works

Suppose you need to call a method called get_information() in the base class from child class , you
can do so using the following code.

super().get_information()
Similarly, you can call base class constructor from child class constructor using the following code.

super().__init__()

Multiple inheritance

Unlike languages like Java and C#, python allows multiple inheritance i.e you can inherit from
multiple classes at the same time like this,

class Subclass(SuperClass1, SuperClass2, ...):


1 # initializer
2 # methods

Let's take an example:

class MySuperClass1():

def method_super1(self):
print("method_super1 method called")

class MySuperClass2():

def method_super2(self):
print("method_super2 method called")

class ChildClass(MySuperClass1, MySuperClass2):

def child_method(self):
print("child method")

20 | P a g e
c = ChildClass()
c.method_super1()
c.method_super2()

Expected Output:

method_super1 method called


method_super2 method called

As you can see becuase ChildClass inherited MySuperClass1, MySuperClass2, object of ChildClass is now
able to access method_super1() and method_super2().

Overriding methods

To override a method in the base class, sub class needs to define a method of same signature. (i.e
same method name and same number of parameters as method in base class).

class A():

def __init__(self):
self.__x = 1

def m1(self):
print("m1 from A")

class B(A):

def __init__(self):
self.__y = 1

def m1(self):
print("m1 from B")

c = B()
c.m1()

Expected Output:

m1 from B
Here we are overriding m1() method from the base class. Try commenting m1() method in B class and
now m1() method from Base class i.e class A will run.

21 | P a g e
Expected Output:

m1 from A

isinstance() function

The isinstance() function is used to determine whether the object is an instance of the class or not.

Syntax: isinstance(object, class_type)

>>> isinstance(1, int)


True

>>> isinstance(1.2, int)


False

>>> isinstance([1,2,3,4], list)


True

Overloading and Overriding-In-Python

Overloading and Overriding in Python are the two main object-oriented concepts that allow
programmers to write methods that can process a variety of different types of functionalities with the same
name. This helps us to implement Polymorphism and achieve consistency in our code. Let's look at an
example to understand the concept of overloading and overriding:

Consider a scenario where you must select arrows for shooting practice in archery. Here, the concept of
overloading and overriding can be depicted as follows:

overloading-and-overriding-in-python

Consider a case where you have 3 similar-looking arrows with different functionalities or properties.
Now, depending on the condition of shooting, the arrow is selected. This is known as overloading. Hence,

22 | P a g e
overloading implies using numerous methods with the same name but accepting a different number of
arguments.

Now, consider another case where your Dad has an arrow. You have access to this arrow, as you
inherited it. But, you also bought the same type of arrow for yourself. Now, while shooting if you are
choosing your arrow over your Dad's arrow, then it is known as overriding.

Now, let's look at overloading and overriding in Python from a technical point of view.

Method Overloading in Python

Method Overloading in Python is a type of Compile-time Polymorphism using which we can define
two or more methods in the same class with the same name but with a different parameter list.

We cannot perform method overloading in the Python programming language as everything is


considered an object in Python. Out of all the definitions with the same name, it uses the latest definition
for the method. Hence, we can define numerous methods with the same name, but we can only use the
latest defined method. In Python, we can make our code have the same features as overloaded functions by
defining a method in such a way that there exists more than one way to call it. For example:

Code:

# Function to take multiple arguments

def sum_number(*args):

# variable to store the sum of numbers

result = 0

# accessing the arguments

for num in args:

result += num

# Output

print("Sum : ", result)

# Driver Code

if(__name__ == "__main__"):

print("Similar to Method Overloading\n")

print("Single Argument ->", end = " ")

sum_number(10)

print("Two Arguments ->", end = " ")

sum_number(30, 2)

print("Multiple Arguments ->", end = " ")

sum_number(1, 2, 3, 4, 5)

23 | P a g e
Output:

Similar to the Method of Overloading

Single Argument -> Sum : 10

Two Arguments -> Sum : 32

Multiple Arguments -> Sum : 15

Method Overriding in Python

Method Overriding is a type of Run-time Polymorphism. A child class method overrides (or provides
its implementation) the parent class method of the same name, parameters, and return type. It is used to
over-write (redefine) a parent class method in the derived class. Let's look at an example:

Code:

# Parent Class

class A:

def first(self):

print("First function of class A")

def second(self):

print('Second function of class A')

# Derived Class

class B(A):

# Overriden Function

def first(self):

print("Redefined function of class A in class B")

def display(self):

print('Display Function of Child class')

# Driver Code

if(__name__ == "__main__"):

# Creating child class object

child_obj = B()

24 | P a g e
# Calling the overridden method

print("Method Overriding\n")

child_obj.first()

# Calling the original Parent class method

# Using parent class object.

A().first()

Output:

Method Overriding

The redefined function of class A in class B

The first function of class A

Quiz Pop

new tag

Quiz Type

SCQ

100

Success Rate:

35%

Difference Between Overloading and Overriding in Python

Method Overloading Method Overriding

Compile-time Polymorphism. Run-time Polymorphism.

Occurs in the same class. Occurs in two classes via inheritance.

Methods must have the same name Methods must have the same name
and different parameters. and same parameters.

Parameters must differ in number, Parameters and return types must be


type, or both. the same.

Return type must be the same or a


Return type can be different.
subtype.

Achieves runtime polymorphism and


Improves code readability.
dynamic dispatch.

Can occur within the same class or Occurs in a subclass that inherits
its subclasses. from a superclass.

25 | P a g e
Method Overloading Method Overriding

Allows same method name for Redefines a method in the subclass


similar operations. with a specific implementation.

Determined at compile-time. Determined at runtime.

Multiple methods can have the same Provides a specific implementation


name with different parameters in of a method defined in the
the same class or its subclasses. superclass in its subclass.

Method overloading is used for


Method overriding is used for
creating methods with similar
providing a specific implementation
functionalities but different input
of a method in a subclass.
parameters.

The choice of which method to The choice of which method to


invoke is made at compile-time invoke is made at runtime based on
based on the method signature. the object’s type.

Method overriding is a fundamental


Method overloading is less related concept in object-oriented
to inheritance and polymorphism. programming and is closely related
to inheritance and polymorphism.

Method Resolution Order in Python

In this tutorial, we will learn about method resolution order, which is also known as the MRO. It is an
essential concept of Python inheritance.

Method resolution order describes the search path of the class which Python uses to get the appropriate
method in classes that contain the multi-inheritance.

Introduction
As we know that, a class that being inherited is called the Subclass or Parent class, while the class
that inherits is known as a child class or subclass. In the multi-inheritance, a class can consist of many
functions, so the method resolution order technique is used to search the order in which the base class is
executed.

In simple words - "The method or attributes is explored in the current class, if the method is not present in
the current class, the search moves to the parent classes, and so on". This is an example of a depth-first
search.

It plays an essential role in multiple inheritance where the same method can be found in the multiple
superclasses.

26 | P a g e
To understand it in a better way, the following example is given here.

Example -

class A:

def myname(self):

print("I am a class A")

class B(A):

def myname(self):

print("I am a class B")

class C(A):

def myname(self):

print("I am a class C")

c = C()

print(c.myname())

Output:

I am a class C

Explanation -

There is a multiple inheritance in the above code. We have defined three-class called A, B, and C,
and these classes have the same name method called myname(). We created an object class C. The object
invoked class C, not the class, while class C inherited the class A method.

The order is followed in the above code is class B - > class A. This technique is known as MRO
(method resolution order).

Let's understand another example of multiple inheritance.

Example -

class A:

def myname(self):

print(" I am a class A")

class B(A):

def myname(self):

print(" I am a class B")

class C(A):

def myname(self):

print("I am a class C")

27 | P a g e
# classes ordering

class D(B, C):

pass

d = D()

d.myname()

Output:

I am a class B

Explanation -

In the above code, we have created another D class without defining class attributes that inherited
B and C class. When we invoked the method myname(), it goes to class D and searches for the myname()
function. But class D doesn't have any declaration. Hence, the search transfers to class B, gets the
myname() function, and returns the result. The search will take place as follows.

Class D -> Class B -> Class C -> Class A

If class B wouldn't have a method, it will invoke the class C method.

Here, we are suggesting you remove the class B method and check what happens. By doing this, you will
get an idea of how the method resolution works.

Duck typing in Python

In this tutorial, we will learn about duck typing. It is a popular term in Python, and it comes from
saying, "If it walks like duck, swims like duck, looks like a duck, then it probably should be a duck."

The above statement gives an idea to identify a duck. Here we don't need to have a genomic sequence of
the duck. We draw our conclusion by its behavior and external appearances.

We will discuss what is exactly mean of duck typing in Python programming.

Python follows the EAFP (Easier to Ask Forgiveness than Permission) rather than the LBLY (Look Before You
Leap) philosophy. The EAFP is somewhat linked to the "duck typing" style.

Play

Next

Mute

Current Time

0:00

Duration

18:10

Fullscreen

Backward Skip 10s

28 | P a g e
Play Video

Forward Skip 10s

Advertisement

Dynamic vs. Static Typing

The main reason for using duck typing is to provide support for dynamic typing in Python
programming. In Python, we don't need to specify the variable's data type and we can reassign the
different data type values to same variable in further code. Let's see the following example.

Example -

x = 12000

print(type(x))

x = 'Dynamic Typing'

print(type(x))

x = [1, 2, 3, 4]

print(type(x))

Output:

<class 'int'>

<class 'str'>

<class 'list'>

As we can see in the above code, we assigned an integer to a variable x, making it of the int type.
Then, we assigned a string and a list to the same variable. Python interpreter accepts the changes of data
types of the same variable. This is a dynamic typing behavior. Many other programming languages such as
Java, swift are the static type. We need to declare variable with the data types. In the below example, we
try to do the same thing using the Swift instead of Python.

Example -

# integer value assigning in JavaScript

var a = 10

# Assinging string in swift

a = 'Swift language'

Above code cannot be compiled, because we couldn't assign a string in Swift language. Because variable a
was declared as an integer.

29 | P a g e
Concept of Duck Typing

Earlier, we have discussed that Python is a dynamic typed language. However, we can use the dynamic
approach with custom data types. Let's understand the following example.

Example -

class VisualStudio:

def execute(self):

print('Compiling')

print('Running')

print('Spell Check')

print('Convention Check')

class Desktop:

def code(self, ide):

ide.execute()

ide = VisualStudio()

desk = Desktop()

desk.code(ide)

Output:

Compiling

Running

Spell Check

Convention Check

In the above code, we have created a VisualStudio class that has to execute() method. In the
desktop-class, we have passed the ide as an argument in the code(). An ide is an object of VisualStudio
class. With the help of ide, we called the execute() method of VisualStudio class.

Another example.

Example - 2

class Duck:

def swim(self):

print("I'm a duck, and I can swim.")

class Sparrow:

def swim(self):

print("I'm a sparrow, and I can swim.")

30 | P a g e
class Crocodile:

def swim_walk(self):

print("I'm a Crocodile, and I can swim, but not quack.")

def duck_testing(animal):

animal.swim()

duck_testing(Duck())

duck_testing(Sparrow())

duck_testing(Crocodile())

Output:

I'm a duck, and I can swim.

I'm a sparrow, and I can swim.

Traceback (most recent call last):

File "<string>", line 24, in <module>

File "<string>", line 19, in duck_testing

AttributeError: 'Crocodile' object has no attribute 'swim'

In the above code, the Duck class's instance is reflected by calling the duck_testing function. It also
happens with the Sparrow class, which implements the swim() function. But in the case of the Crocodile
class, it fails the duck testing evaluation because it doesn't implement the swim() function.

Abstract Classes in Python


An abstract class can be considered a blueprint for other classes. It allows you to create a set of
methods that must be created within any child classes built from the abstract class.
A class that contains one or more abstract methods is called an abstract class. An abstract method is a
method that has a declaration but does not have an implementation.
We use an abstract class while we are designing large functional units or when we want to provide a
common interface for different implementations of a component.

Abstract Base Classes in Python


By defining an abstract base class, you can define a common Application Program
Interface(API) for a set of subclasses. This capability is especially useful in situations where a third party is
going to provide implementations, such as with plugins, but can also help you when working in a large
team or with a large code base where keeping all classes in your mind is difficult or not possible.
Working on Python Abstract classes
By default, Python does not provide abstract classes. Python comes with a module that provides the base
for defining Abstract Base classes(ABC) and that module name is ABC.

31 | P a g e
ABC works by decorating methods of the base class as an abstract and then registering concrete
classes as implementations of the abstract base. A method becomes abstract when decorated with the
keyword @abstractmethod.

Example 1:
This code defines an abstract base class called “Polygon” using the ABC (Abstract Base Class)
module in Python. The “Polygon” class has an abstract method called “noofsides” that needs to be
implemented by its subclasses.
There are four subclasses of “Polygon” defined: “Triangle,” “Pentagon,” “Hexagon,” and “Quadrilateral.”
Each of these subclasses overrides the “noofsides” method and provides its own implementation by
printing the number of sides it has.
In the driver code, instances of each subclass are created, and the “noofsides” method is called on each
instance to display the number of sides specific to that shape.

# Python program showing

# abstract base class work

from abc import ABC, abstractmethod

class Polygon(ABC):

@abstractmethod

def noofsides(self):

pass

class Triangle(Polygon):

# overriding abstract method

def noofsides(self):

print("I have 3 sides")

class Pentagon(Polygon):

# overriding abstract method

def noofsides(self):

print("I have 5 sides")

class Hexagon(Polygon):

# overriding abstract method

def noofsides(self):

print("I have 6 sides")

32 | P a g e
class Quadrilateral(Polygon):

# overriding abstract method

def noofsides(self):

print("I have 4 sides")

# Driver code

R = Triangle()

R.noofsides()

K = Quadrilateral()

K.noofsides()

R = Pentagon()

R.noofsides()

K = Hexagon()

K.noofsides()

Output

I have 3 sides

I have 4 sides
I have 5 sides

I have 6 sides

Example 2:
Here, This code defines an abstract base class called “Animal” using the ABC (Abstract Base Class)
module in Python. The “Animal” class has a non-abstract method called “move” that does not have any
implementation. There are four subclasses of “Animal” defined: “Human,” “Snake,” “Dog,” and “Lion.” Each
of these subclasses overrides the “move” method and provides its own implementation by printing a
specific movement characteristic.

# Python program showing

# abstract base class work

from abc import ABC, abstractmethod

class Animal(ABC):

def move(self):

pass

33 | P a g e
class Human(Animal):

def move(self):

print("I can walk and run")

class Snake(Animal):

def move(self):

print("I can crawl")

class Dog(Animal):

def move(self):

print("I can bark")

class Lion(Animal):

def move(self):

print("I can roar")

# Driver code

R = Human()

R.move()

K = Snake()

K.move()

R = Dog()

R.move()

K = Lion()

K.move()

Output
I can walk and run

I can crawl
I can bark

I can roar

34 | P a g e
Concrete Methods in Abstract Base Classes
Concrete classes contain only concrete (normal) methods whereas abstract classes may contain
both concrete methods and abstract methods.
The concrete class provides an implementation of abstract methods, the abstract base class can also
provide an implementation by invoking the methods via super(). Let look over the example to invoke the
method using super():

# Python program invoking a


# method using super()

from abc import ABC

class R(ABC):
def rk(self):
print("Abstract Base Class")

class K(R):
def rk(self):
super().rk()
print("subclass ")

# Driver code
r = K()
r.rk()

Output

Abstract Base Class


subclass
In the above program, we can invoke the methods in abstract classes by using super().

Interfaces in Python

In software engineering, an interface is a software architectural pattern. It is similar to a class but its
methods just have prototype signature definition without any executable code or implementation body. The
required functionality must be implemented by the methods of any class that inherits the interface.

The method defined without any executable code is known as abstract method.

Interfaces in Python

In languages like Java and Go, there is keyword called interface which is used to define an interface. Python
doesn't have it or any similar keyword. It uses abstract base classes (in short ABC module) and
@abstractmethod decorator to create interfaces.

Key Point: In Python, abstract classes are also created using ABC module.

An abstract class and interface appear similar in Python. The only difference in two is that the
abstract class may have some non-abstract methods, while all methods in interface must be abstract, and
the implementing class must override all the abstract methods.

35 | P a g e
Rules for implementing Python Interfaces

 We need to consider the following points while creating and implementing interfaces in Python −
 Methods defined inside an interface must be abstract.
 Creating object of an interface is not allowed.
 A class implementing an interface needs to define all the methods of that interface.
 In case, a class is not implementing all the methods defined inside the interface, the class must be
declared abstract.
 Learn Python in-depth with real-world projects through our Python certification course. Enroll and
become a certified expert to boost your career.

Implementing interfaces in Python

We can create and implement interfaces in two ways −

 Formal Interface
 Informal Interface

Formal Interface

Formal interfaces in Python are implemented using abstract base class (ABC). To use this class, you need to
import it from the abc module.

Example

In this example, we are creating a formal interface with two abstract methods.

from abc import ABC, abstractmethod

# creating interface

class demoInterface(ABC):

@abstractmethod

def method1(self):

print ("Abstract method1")

return

@abstractmethod

def method2(self):

print ("Abstract method1")

return

Let us provide a class that implements both the abstract methods.

# class implementing the above interface

class concreteclass(demoInterface):

36 | P a g e
def method1(self):

print ("This is method1")

return

def method2(self):

print ("This is method2")

return

# creating instance

obj = concreteclass()

# method call

obj.method1()

obj.method2()

Output

Output:

This is method1

This is method2

Informal Interface

In Python, the informal interface refers to a class with methods that can be overridden. However, the
compiler cannot strictly enforce the implementation of all the provided methods. This type of interface works
on the principle of duck typing. It allows us to call any method on an object without checking its type, as
long as the method exists.

Example

In the below example, we are demonstrating the concept of informal interface.

class demoInterface:

def displayMsg(self):

pass

class newClass(demoInterface):

def displayMsg(self):

print ("This is my message")

# creating instance

37 | P a g e
obj = newClass()

# method call

obj.displayMsg()

Output

On running the above code, it will produce the following output −

This is my message

What are the Types of Errors in Python?

Errors are problems that occur in the program due to an illegal operation performed by the user or
by the fault of a programmer, which halts the normal flow of the program. Errors are also termed bugs or
faults. There are mainly two types of errors in python programming. Let us learn about both types of python
errors:

The three main types of errors in Python are syntax errors, runtime errors, and logical errors:

 Syntax errors

Similar to grammar mistakes in English, these occur when the rules of the Python language are not
followed. The Python interpreter can identify these errors during code writing.

 Runtime errors

Also known as exceptions, these occur when the code has the correct syntax but encounters a problem
while running. These errors can be caused by unexpected conditions like dividing by zero, accessing an
index out of range, or calling a function that doesn't exist.

 Logical errors
These occur when the code runs without any syntax or runtime errors but produces incorrect results. These
errors are the most difficult to find because they don't produce error messages. They can be caused by
incorrect assumptions, incomplete understanding of the problem, or incorrect use of algorithms or
formulas.
Compile time is when the programming code is converted to machine code, while runtime is when the
program is running.

Syntax Errors

A syntax error is one of the most basic types of error in programming. Whenever we do not write the
proper syntax of the python programming language (or any other language) then the python interpreter
or parser throws an error known as a syntax error. The syntax error simply means that the python parser is
unable to understand a line of code.

Let us take an example to understand the syntax error better.

number = 100

if number > 50

print("Number is greater than 50!")

38 | P a g e
Output:

File "test.py", line 3

if number > 50

SyntaxError: invalid syntax

As we can see in the example above, the python interpretation raised a syntax error saying invalid
syntax. Since we have missed the semicolon (:) after the if statement so that's why the python interpreter
raised a syntax error.

Some of the general syntax errors can be typing errors (errors), incorrect indentation, or incorrect
arguments. In case of syntax errors, we should look at our code and try to understand the problem.

Note: In various IDEs (Integrated Development Environment), the syntax error(s) are shown by red dashed
lines.

Logical Errors

As we have seen above there are two main types of python errors. We already have studied the
syntax error, let us now learn about the logical errors in python.

Logical Errors are those errors that cannot be caught during compilation time. As we cannot check these
errors during compile time, we name them Exceptions. Since we cannot check the logical errors during
compilation time, it is difficult to find them.

There is one more name of logical error. Run time errors are those errors that cannot be caught during
compilation time. So, run-time can cause some serious issues so we should handle them effectively.

Let us now talk about some of the most common logical types of errors in python programming.

ZeroDivisionError Exception

ZeroDivisionError is raised by the Python interpreter when we try to divide any number by zero. Let us take
an example to understand the ZeroDivisionError.

number = 100

divided_by_zero = number / 0

print(divided_by_zero)

Output:

Traceback (most recent call last):

File "d:\test.py", line 2, in <module>

divided_by_zero = number / 0

ZeroDivisionError: division by zero

Indentation is not Correct

39 | P a g e
The Indentation error is another type of error in python that can be summed up inside the syntax
error. As we know, we use indentation to define a block of code in python. So, in case of improper
indentation, the Python interpreter raises an Indentation error. Let us take an example to understand the
Indentation Error.

number = 57

if number == 57:

print(57)

Output:

File "d:\test.py", line 4

print(57)

IndentationError: expected an indented block

Exception Handling

Exception handling enables you handle errors gracefully and do something meaningful about it.
Like display a message to user if intended file not found. Python handles exception using try, except block.

Syntax:

try:

# write some code

# that might throw exception

except <ExceptionType>:

# Exception handler, alert the user

As you can see in try block you need to write code that might throw an exception. When exception occurs
code in the try block is skipped. If there exist a matching exception type in `except clause then it's handler
is executed.

Let's take an example:

try:

f = open('somefile.txt', 'r')

print(f.read())

f.close()

except IOError:

print('file not found')

The above code work as follows:

First statement between try and except block are executed.

If no exception occurs then code under except clause will be skipped.

40 | P a g e
If file don't exists then exception will be raised and the rest of the code in the try block will be skipped

When exceptions occurs, if the exception type matches exception name after except keyword, then the
code in that except clause is executed.

note:

The above code is only capable of handling IOError exception. To handle other kind of exception you need
to add more except clause.

A try statement can have more than once except clause, It can also have optional else and/or finally
statement.

try:

<body>

except <ExceptionType1>:

<handler1>

except <ExceptionTypeN>:

<handlerN>

except:

<handlerExcept>

else:

<process_else>

finally:

<process_finally>

The except clause is similar to elif. When exception occurs, it is checked to match the exception type in
except clause. If match is found then handler for the matching case is executed. Also note that in last
except clause ExceptionType is omitted. If exception does not match any exception type before the last
except clause, then the handler for last except clause is executed.

note:

Statements under the else clause run only when no exception is raised.

note:

Statements in the finally clause will run every time no matter exception occurs or not.

Now let's take an example.

try:

num1, num2 = eval(input("Enter two numbers, separated by a comma : "))

result = num1 / num2

print("Result is", result)

except ZeroDivisionError:

41 | P a g e
print("Division by zero is error !!")

except SyntaxError:

print("Comma is missing. Enter numbers separated by comma like this 1, 2")

except:

print("Wrong input")

else:

print("No exceptions")

finally:

print("This will execute no matter what")

note:

The eval() function lets a python program run python code within itself, eval() expects a string argument.

To learn more about the eval() visit eval() in Python.

Raising exceptions

To raise your exceptions from your own methods you need to use raise keyword like this

raise ExceptionClass("Your argument")

Let's take an example

def enterage(age):

if age < 0:

raise ValueError("Only positive integers are allowed")

if age % 2 == 0:

print("age is even")

else:

print("age is odd")

try:

num = int(input("Enter your age: "))

enterage(num)

except ValueError:

print("Only positive integers are allowed")

except:

print("something is wrong")

42 | P a g e
Expected Output:

Enter your age: 12

age is even

Again run the program and enter a negative number.

Expected Output:

Enter your age: -12

Only integers are allowed

Using Exception objects

Now you know how to handle exception, in this section we will learn how to access exception
object in exception handler code. You can use the following code to assign exception object to a variable.

try:

# this code is expected to throw exception

except ExceptionType as ex:

# code to handle exception

As you can see you can store exception object in variable ex. Now you can use this object in exception
handler code.

try:

number = eval(input("Enter a number: "))

print("The number entered is", number)

except NameError as ex:

print("Exception:", ex)

Run the program and enter a number.

Expected Output:

Enter a number: 34

The number entered is 34

Again run the program and enter a string .

Expected Output:

Enter a number: one

Exception: name 'one' is not defined

Creating custom exception class

You can create a custom exception class by extending BaseException class or subclass of BaseException.

43 | P a g e
python-exception-classes.jpg

As you can see from most of the exception classes in python extends from the BaseException class. You
can derive you own exception class from BaseException class or from sublcass of BaseException like
RuntimeError.

Create a new file called NegativeAgeException.py and write the following code.

class NegativeAgeException(RuntimeError):

def __init__(self, age):

super().__init__()

self.age = age

Above code creates a new exception class named NegativeAgeException, which consists of only
constructor which call parent class constructor using super().__init__() and sets the age.

Using custom exception class

def enterage(age):

if age < 0:

raise NegativeAgeException("Only positive integers are allowed")

if age % 2 == 0:

print("age is even")

else:

print("age is odd")

try:

num = int(input("Enter your age: "))

enterage(num)

except NegativeAgeException:

print("Only positive integers are allowed")

except:

print("something is wrong")

44 | P a g e
Types of Exceptions:

Built-in Exceptions

The table below shows built-in exceptions that are usually raised in Python:

Exception Description

ArithmeticError Raised when an error occurs in numeric calculations

AssertionError Raised when an assert statement fails

AttributeError Raised when attribute reference or assignment fails

Exception Base class for all exceptions

EOFError Raised when the input() method hits an "end of file"


condition (EOF)

FloatingPointError Raised when a floating point calculation fails

GeneratorExit Raised when a generator is closed (with the close()


method)

ImportError Raised when an imported module does not exist

IndentationError Raised when indentation is not correct

IndexError Raised when an index of a sequence does not exist

KeyError Raised when a key does not exist in a dictionary

KeyboardInterrupt Raised when the user presses Ctrl+c, Ctrl+z or Delete

LookupError Raised when errors raised cant be found

MemoryError Raised when a program runs out of memory

NameError Raised when a variable does not exist

NotImplementedError Raised when an abstract method requires an inherited


class to override the method

45 | P a g e
Exception Description

OSError Raised when a system related operation causes an error

OverflowError Raised when the result of a numeric calculation is too


large

ReferenceError Raised when a weak reference object does not exist

RuntimeError Raised when an error occurs that do not belong to any


specific exceptions

StopIteration Raised when the next() method of an iterator has no


further values

SyntaxError Raised when a syntax error occurs

TabError Raised when indentation consists of tabs or spaces

SystemError Raised when a system error occurs

SystemExit Raised when the sys.exit() function is called

TypeError Raised when two different types are combined

UnboundLocalError Raised when a local variable is referenced before


assignment

UnicodeError Raised when a unicode problem occurs

UnicodeEncodeError Raised when a unicode encoding problem occurs

UnicodeDecodeError Raised when a unicode decoding problem occurs

UnicodeTranslateError Raised when a unicode translation problem occurs

ValueError Raised when there is a wrong value in a specified data


type

ZeroDivisionError Raised when the second operator in a division is zero

46 | P a g e

You might also like