Python: Inheritance and Polymorphism
Python Inheritance and Polymorphism
1 Overview
📘 Inheritance
In Python, Inheritance is a programming paradigm based on the concept of “objects”, which can contain data in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods). Inheritance in Python is a key feature of object-oriented programming that allows a new class (child/subclass) to inherit attributes and methods from an existing class (parent/superclass). This mechanism promotes code reuse and models real-world hierarchical relationships. In other words, building on existing classes’ code.
2 Main Aspects of Inheritance in Python
- Basic Concept: A child class inherits the behaviors (methods) and properties (attributes) of a parent class. The child class can use these inherited features directly or override them with its own implementations. This represents an “is-a” relationship (e.g., a Dog “is-a” Animal).
- Syntax: The child class is defined by placing the parent class name in parentheses after the child class name:
This tells Python the ChildClass inherits from ParentClass.
- Method Overriding: The child class can provide a new definition for a method inherited from the parent, changing its behavior while keeping the same method name. This is essential for customizing behavior.
- Using
super()
: Thesuper()
function allows a child class to call methods (like__init__
) from its parent class, enabling proper initialization or method extension. - Types of Inheritance: Python supports several inheritance types:
- Single Inheritance: One child, one parent.
- Multiple Inheritance: One child, multiple parents.
- Multilevel Inheritance: Chain of inheritance across multiple levels.
- Hierarchical Inheritance: Multiple children inheriting from one parent.
- Advantages:
- Reuse existing code without duplication.
- Organize related classes into hierarchies.
- Easy maintenance and extensibility of code.
- Polymorphism: Child classes can be treated as instances of their parent class, enabling flexible code.
2.1 Simple Example
Output:
Animal name: Buddy
Buddy barks
This shows the child class Dog
inheriting info()
from Animal
and adding its own sound()
method.
2.2 More Inheritance Examples
3 Multiple Class Inheritance
4 The super()
Function
- Call method from parent class.
5 Method Overriding
- Modify or extend inherited behavior.
class Vehicle:
def __init__(self, brand, wheels):
self.brand = brand
self.wheels = wheels
def description(self):
print(f"A mode of transport on {self.wheels} wheels.")
class Car(Vehicle):
def __init__(self, brand, wheels, doors):
super().__init__(brand, wheels)
self.doors = doors
def description(self):
# Override parent's method behavior
print(f"A personal mode of transport on {self.wheels} wheels.")
- A
Car
object is both of typeVehicle
andCar
:
6 Polymorphism
- Polymorphism is an object-oriented programming concept.
- Refers to the ability of a variable, function, or object to take on multiple forms.
- Class objects with a common parent class may have functions with the same name, but with different behaviors.
- All instances have a
description()
method.
7 Example
Area: 78.54
Area: 24
8 More realistic example
HR program to track employees in a company.
class Worker:
def __init__(self, id_card, phone_num, address, bank_iban):
self.id_card = id_card
self.phone_num = phone_num
self.address = address
self.bank_iban = bank_iban
@abstractmethod
def report_work(self):
pass
@abstractmethod
def calculate_monthly_salary(self):
pass
def get_contact_info(self):
return f"Phone: {self.phone_num}, Address: {self.address}"
def get_payment_details(self):
return f"IBAN: {self.bank_iban}, Address: {self.address}"
def change_bank_iban(self, new_iban, signed_certificate):
# Check valid signed certificate and, if valid, change IBAN
...
class Employee(Worker):
def __init__(self, id_card, phone_num, address,
bank_iban, year_salary):
super().__init__(id_card, phone_num, address, bank_iban)
self.year_salary = year_salary
def report_work(self):
return "Employee reporting: I've worked 8 hours today."
def calculate_monthy_salary(self):
# Consider gross year salary, calculate monthly,
# subtract SS and IRPF, etc.
...
def Executive(Employee):
def __init__(self, id_card, phone_num, address,
bank_iban, year_salary, incentive=None):
super().__init__(id_card, phone_num, address,
bank_iban, year_salary)
self.incentive = incentive
self.tasks_completed = []
def report_work(self):
return "Executive reporting: I've completed objectives X, Y."
def calculate_monthly_salary(self):
fix_salary = super().calculate_monthly_salary()
# Add incentives
...
class Freelancer(Worker):
def __init__(self, id_card, phone_num, address,
bank_iban, hourly_rate):
super().__init__(id_card, phone_num, address, bank_iban)
self.hourly_rate = hourly_rate
def report_work(self):
return "Freelancer reporting: I've worked 4 hours today."
def calculate_monthy_salary(self):
# Consider hourly_rate, hours worked this month, etc.
...
class Contractor(Worker):
def __init__(self, id_card, phone_num, address, bank_iban, contract_fee):
super().__init__(id_card, phone_num, address, bank_iban)
self.contract_fee = contract_fee
def report_work(self):
return "Contractor reporting: Project completed today."
def calculate_monthy_salary(self):
# Consider contract_fee, completion of the project, etc.
...
def PaymentSystem():
def process_payroll(workers):
"""
Process payroll for a list of workers, regardless of their
specific type. This function uses polymorphism to call each
worker's own salary calculation method.
"""
for worker in workers:
print(f"Processing payroll for {worker.id_card}")
salary = worker.calculate_monthly_salary()
print(f"Salary: {salary}")
payment_details = worker.get_payment_details()
print(f"Payment will be transferred to {payment_details}\n")
status = pay_monthly_salary(salary, payment_details)
if status:
print(f"{salary}€ correctly paid to {worker.id_card}")
else:
print(f"Payment error: {worker.id_card}.")