Object Oriented Programming(Python)
Emmanuel Ali(PhD)
May 7, 2026
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 1 / 32
Outline
1 Inheritance
2 Polymorphism
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 2 / 32
Inheritance
Definition: Inheritance is a fundamental concept in
object-oriented programming that allows a class to inherit
attributes and methods from another class
Purpose: Enables code reuse and establishes a relationship
between classes
Terminology:
Parent/Base/Super class: The class being inherited from
Child/Derived/Sub class: The class that inherits from the parent
class
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 3 / 32
Inheritance
Defining a Base Class (Superclass):
To create a base class, define a class with its attributes and methods.
This class will serve as the template for other classes to inherit from.
class Animal :
def __init__ ( self , name ) :
self . name = name
def speak ( self ) :
pass # This method will be overridden in subclasses
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 4 / 32
Inheritance
Creating a Subclass (Derived Class)
To create a subclass, define a new class and specify the base class in
parentheses after the class name. The subclass inherits the attributes
and methods of the base class. You can also add new attributes and
methods or modify the inherited ones.
class Dog ( Animal ) : # Dog is a subclass of Animal
def speak ( self ) :
return f " { self . name } says Woof ! "
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 5 / 32
Inheritance
Creating Objects from Subclasses
You can create objects of the subclass just like you would with any other
class. Objects of the subclass have access to both the inherited
attributes and methods as well as any new attributes and methods
defined within the subclass.
my_dog = Dog ( " Buddy " )
print ( my_dog . name ) # Access the ' name ' attribute from the
base class
print ( my_dog . speak () ) # Call the ' speak ' method from the
subclass
my_dog is an object of the Dog class and can access the name attribute
from the Animal class and the speak method from the Dog class.
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 6 / 32
class Animal :
def __init__ ( self , species ) :
self . species = species
def make_sound ( self ) :
print ( " Some generic sound " )
class Dog ( Animal ) :
def __init__ ( self , name , breed ) :
# Initialize the parent class
super () . __init__ ( " Canine " )
# Add new attributes
self . name = name
self . breed = breed
# Add new method
def wag_tail ( self ) :
print ( f " { self . name } wags tail happily " )
# Override parent method
def make_sound ( self ) :
print ( " Woof ! Woof ! " )
dog = Dog ( " Rex " , " German Shepherd " )
print ( dog . species ) # Output : Canine
dog . make_sound () # Output : Woof ! Woof !
dog . wag_tail () # Output : Rex wags tail happily
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 7 / 32
Types of Inheritance
Four Types of Inheritance
1 Single Inheritance
2 Multiple Inheritance
3 Multilevel Inheritance
4 Hierarchical Inheritance
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 8 / 32
Types of Inheritance
1. Single Inheritance: A class inherits 3. Multilevel Inheritance: A class
from one parent class inherits from a child class
class A :
class A : pass
pass class B ( A ) : # B inherits from A
class B ( A ) : # B inherits from A pass
pass class C ( B ) : # C inherits from
B ( which inherits from A )
pass
2. Multiple Inheritance: A class inherits
from multiple parent classes
4. Hierarchical Inheritance: Multiple
classes inherit from one class
class A :
pass class A :
class B : pass
pass class B ( A ) : # B inherits from A
class C (A , B ) : # C inherits pass
from both A and B class C ( A ) : # C also inherits
pass from A
pass
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 9 / 32
Inheritance
Inheritance Hierarchy
You can create multiple levels of inheritance, forming an inheritance
hierarchy. For example, you can have a base class ‘Vehicle‘, a subclass
‘Car‘ that inherits from ‘Vehicle‘, and a further subclass ‘ElectricCar‘
that inherits from ‘Car‘. Inheritance hierarchies allow for a structured
way to organize and extend code.
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 10 / 32
class Vehicle :
def __init__ ( self , make , model , year ) :
self . make = make
self . model = model
self . year = year
self . is_running = False
def start_engine ( self ) :
self . is_running = True
print ( f " The { self . year } { self . make }
{ self . model } ' s engine is running . " )
def stop_engine ( self ) :
self . is_running = False
print ( f " The { self . year } { self . make } { self . model } ' s engine
is stopped . " )
class Car ( Vehicle ) :
def __init__ ( self , make , model , year , num_doors ) :
super () . __init__ ( make , model , year )
self . num_doors = num_doors
def honk ( self ) :
print ( f " The { self . year } { self . make } { self . model } beeps its
horn . " )
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 11 / 32
class Bicycle ( Vehicle ) :
def __init__ ( self , make , model , year , frame_type ) :
super () . __init__ ( make , model , year )
self . frame_type = frame_type
def ring_bell ( self ) :
print ( f " The { self . year } { self . make } { self . model } rings its
bell . " )
# Using inheritance
my_car = Car ( " Toyota " , " Camry " , 2022 , 4)
my_bicycle = Bicycle ( " Schwinn " , " Mountain Bike " , 2021 , " Steel " )
my_car . start_engine ()
my_car . honk ()
my_car . stop_engine ()
my_bicycle . start_engine ()
my_bicycle . ring_bell ()
my_bicycle . stop_engine ()
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 12 / 32
Inheritance
The super() function is used to access methods of a parent class.
Commonly used in inheritance to:
Initialize parent class attributes.
Extend or reuse parent class methods.
Dynamically resolves the correct parent class using Python’s
Method Resolution Order (MRO).
General Syntax
super().method_name(arguments)
No need to specify the parent class explicitly.
Works seamlessly in single and multiple inheritance scenarios.
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 13 / 32
Inheritance
class Animal :
def __init__ ( self , name ) :
self . name = name
def speak ( self ) :
return f " { self . name } makes a sound . "
class Dog ( Animal ) :
def __init__ ( self , name , breed ) :
super () . __init__ ( name ) # Call parent constructor
self . breed = breed
def speak ( self ) :
return f " { super () . speak () } { self . name } barks . "
# Usage
dog = Dog ( " Buddy " , " Golden Retriever " )
print ( dog . speak () )
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 14 / 32
class A :
def __init__ ( self ) :
print ( " A 's constructor called " )
class B ( A ) :
def __init__ ( self ) :
super () . __init__ ()
print ( " B 's constructor called " )
class C ( A ) :
def __init__ ( self ) :
super () . __init__ ()
print ( " C 's constructor called " )
class D (B , C ) :
def __init__ ( self ) :
super () . __init__ ()
print ( " D 's constructor called " )
# Usage
d = D ()
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 15 / 32
Inheritance Example
class Person :
def __init__ ( self , name , age ) :
self . name = name
self . age = age
def introduce ( self ) :
print ( f " My name is { self . name } and
I am { self . age } years old . " )
class Student ( Person ) :
def __init__ ( self , name , age , student_id ) :
super () . __init__ ( name , age )
self . student_id = student_id
def study ( self , subject ) :
print ( f " { self . name } with student ID
{ self . student_id } is studying { subject }. " )
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 16 / 32
Inheritance Example
class Teacher ( Person ) :
def __init__ ( self , name , age , employee_id ) :
super () . __init__ ( name , age )
self . employee_id = employee_id
def teach ( self , subject ) :
print ( f " { self . name } with employee ID
{ self . employee_id } is teaching { subject }. " )
# Using inheritance
student = Student ( " Alice " , 20 , " S12345 " )
teacher = Teacher ( " Mr . Smith " , 35 , " T789 " )
student . introduce ()
student . study ( " Math " )
teacher . introduce ()
teacher . teach ( " History " )
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 17 / 32
Inheritance Example
class Person :
def __init__ ( self , name , age ) :
self . name = name
self . age = age
def introduce ( self ) :
print ( f " My name is { self . name } , and
I am { self . age } years old . " )
class Student :
def __init__ ( self , student_id , major ) :
self . student_id = student_id
self . major = major
def study ( self ) :
print ( f " I am studying { self . major } as
a student with ID { self . student_id }. " )
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 18 / 32
Inheritance Example
class Employee :
def __init__ ( self , employee_id , job_title ) :
self . employee_id = employee_id
self . job_title = job_title
def work ( self ) :
print ( f " I work as a { self . job_title } with
employee ID { self . employee_id }. " )
class StudentEmployee ( Person , Student , Employee ) :
def __init__ ( self , name , age , student_id , major ,
employee_id ,
job_title ) :
Person . __init__ ( self , name , age )
Student . __init__ ( self , student_id , major )
Employee . __init__ ( self , employee_id , job_title )
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 19 / 32
Inheritance Example
def introduce ( self ) :
super () . introduce ()
print ( f " My student ID is { self . student_id } ,
and I am majoring in { self . major }. " )
print ( f " My employee ID is { self . employee_id } ,
and I work as a { self . job_title }. " )
# Using multiple inheritance
student_employee = StudentEmployee ( " Alice " , 22 , " S123 " ,
" Computer Science " , " E456 " , " Software Developer " )
student_employee . introduce ()
student_employee . study ()
student_employee . work ()
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 20 / 32
Method Resolution Order (MRO)
Definition: Algorithm that determines the order in which Python looks for methods
and attributes in a hierarchy of classes
Importance: Critical for understanding behavior in multiple inheritance scenarios
View MRO: Use the __mro__ attribute or mro() method
class A :
def method ( self ) :
print ( " Method in A " )
class B ( A ) :
def method ( self ) :
print ( " Method in B " )
class C ( A ) :
def method ( self ) :
print ( " Method in C " )
class D (B , C ) :
pass
print ( D . __mro__ )
# Output : ( < class ' __main__ . D '>, < class ' __main__ . B '>,
# < class ' __main__ . C '>, < class ' __main__ . A '>, < class
' object ' >)
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 21 / 32
The Diamond Problem
A
B C
class A :
def method ( self ) :
print ( " Method in A " )
class B ( A ) :
def method ( self ) :
print ( " Method in B " )
super () . method () # Calls A 's method
class C ( A ) :
def method ( self ) :
print ( " Method in C " )
super () . method () # Calls A 's method
class D (B , C ) :
def method ( self ) :
print ( " Method in D " )
super () . method () # Calls B 's method ( first in MRO )
d = D ()
d . method ()
# Output :
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 22 / 32
isinstance() and issubclass()
isinstance(object, classinfo): Check if an object is an instance of a class or its
subclass
issubclass(class, classinfo): Check if a class is a subclass of another class
class Animal :
pass
class Mammal ( Animal ) :
pass
class Dog ( Mammal ) :
pass
dog = Dog ()
print ( i s i n s t a n c e ( dog , Dog ) ) # True
print ( i s i n s t a n c e ( dog , Mammal ) ) # True
print ( i s i n s t a n c e ( dog , Animal ) ) # True
print ( i s i n s t a n c e ( dog , object ) ) # True - all classes inherit from
object
print ( i s s u b c l a s s ( Dog , Mammal ) ) # True
print ( i s s u b c l a s s ( Dog , Animal ) ) # True
print ( i s s u b c l a s s ( Mammal , Dog ) ) # False
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 23 / 32
Polymorphism
Polymorphism is a fundamental concept in object-oriented programming (OOP)
that allows objects of different classes to be treated as objects of a common
base class. It enables you to write code that can work with objects of different
types, often in a way that abstracts away the specific details of each type.
Polymorphism is achieved through method overriding and dynamic binding in
Python.
Polymorphism is a concept that promotes code reusability and flexibility in
object-oriented programming. It allows you to write code that can adapt to
different types of objects, making your programs more versatile and easier to
maintain.
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 24 / 32
Polymorphism
Base Class and Method
Start by defining a base class with a method that you want to make
polymorphic. The base class provides a common interface that will be
overridden in subclasses.
class Animal :
def speak ( self ) :
pass # This method will be overridden in
subclasses
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 25 / 32
Polymorphism
Subclasses and Method Override
Create multiple subclasses that inherit from the base class. Each
subclass provides its own implementation of the method to achieve
polymorphism. This allows different types of objects to have the same
method name but behave differently.
class Dog ( Animal ) :
def speak ( self ) :
return " Woof ! "
class Cat ( Animal ) :
def speak ( self ) :
return " Meow ! "
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 26 / 32
Polymorphism
Using Polymorphism
You can create objects of different classes and use the common method
without knowing the specific subclass. Python will dynamically bind the
method call to the appropriate subclass method.
def animal_sound ( animal ) :
return animal . speak ()
my_dog = Dog ()
my_cat = Cat ()
print ( animal_sound ( my_dog ) ) # Output : " Woof !"
print ( animal_sound ( my_cat ) ) # Output : " Meow !"
The ’animal_sound’ function accepts an ’Animal’ object as a parameter.
It doesn’t know whether the object is a ’Dog’ or a ’Cat’. When you call
’[Link]()’ within the function, Python uses dynamic binding to
call the appropriate ‘speak‘ method based on the actual object type.
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 27 / 32
Polymorphism
class Shape :
def area ( self ) :
pass # This method will be overridden in subclasses
class Circle ( Shape ) :
def __init__ ( self , radius ) :
self . radius = radius
def area ( self ) :
return 3.14 * self . radius **2
class Rectangle ( Shape ) :
def __init__ ( self , width , height ) :
self . width = width
self . height = height
def area ( self ) :
return self . width * self . height
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 28 / 32
Polymorphism
circle = Circle (5)
rectangle = Rectangle (4 , 6)
print ( f " Area of the circle : { circle . area () } " ) # Output :
78.5
print ( f " Area of the rectangle : { rectangle . area () } " ) #
Output : 24
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 29 / 32
Exercise
You are designing a simulation for a zoo management system. The system must represent
different types of animals. All animals share common behaviors, but each species has some
specific traits and behaviors.
Instructions:
Create a base class Animal with:
Attributes: name, species
Method: make_sound() → prints a generic sound
Create subclasses:
Lion → make_sound() prints "Roar"
Elephant → make_sound() prints "Trumpet"
Snake → make_sound() prints "Hiss"
Create a list of mixed animals and call make_sound() on each.
Additionally: Add method daily_task() in base class and override:
Lion: Patrols the territory
Elephant: Takes a mud bath
Snake: Basks in the sun
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 30 / 32
Exercise
A store sells both physical and digital products, each with different shipping behaviours.
Use inheritance and polymorphism to model this distinction.
Instructions:
1 Create a Base Class:
Define a class Product with attributes name and price.
Add a method get_shipping_info() that returns "Shipping info not
defined".
2 Create a Subclass — Physical Product:
Define PhysicalProduct(Product) with an extra attribute weight_kg.
Override get_shipping_info() to return:
"Ships in 3–5 days. Weight: 2.5 kg"
3 Create a Subclass — Digital Product:
Define DigitalProduct(Product) with an extra attribute file_size_mb.
Override get_shipping_info() to return:
"Instant download. Size: 150 MB"
4 Demonstrate Polymorphism:
Create a list containing one PhysicalProduct and one DigitalProduct.
Loop through the list and call get_shipping_info() on each item.
Observe that the correct version executes for each type.
5 Additionally:
Add a describe() method to Product that prints:
"Product: Headphones, Price: $45.00"
Ensure both subclasses inherit it without redefining it.
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 31 / 32
Exercise
Use class inheritance to model geometric shapes and apply polymorphism to
calculate area and draw shapes.
Instructions:
Create a base class Shape with:
Method: area() → returns 0
Method: draw() → prints "Drawing a shape"
Create subclasses:
Circle (attribute: radius)
Rectangle (attributes: width, height)
Triangle (attributes: base, height)
Override area() in each subclass to compute area correctly:
Circle: πr2
Rectangle: width × height
Triangle: 12 × base × height
Override draw() in each subclass with a custom message.
Create a list of mixed shapes, and call draw() and area().
Emmanuel Ali(PhD) 2nd Semester May 7, 2026 32 / 32