Object-Oriented Programming (OOP) organizes code into objects - bundles of data (attributes) and behavior (methods).
It makes programs modular, reusable, and easier to maintain.
1. Classes and Objects
i. Class
A class is a blueprint for creating objects. It defines attributes (data) and methods (functions).
class Car:
make = "CrossOver SUV"
ii. Object
An object is an instance of a class - like an actual car built from the blueprint.
2. The __init__ Method (Constructor)
When you create an object from a class, Python automatically calls a special method named __init__.
This method is known as the constructor, and its job is to initialize the object’s attributes - setting up its starting state.
It usually takes parameters that define the object’s initial data.
The first parameter is always self, which refers to the specific object being created.
Example1
class Car:
make = "CrossOver SUV"
def __init__(self, brand, color, max_speed, model):
self.brand = brand
self.color = color
self.max_speed = max_speed
self.model = model
def start(self):
print(f"The {self.brand} car has started")
def stop(self, time):
print(f"The {self.brand} car has stopped at {time}pm.")
def acceleration(self, top_speed):
print(f"The {self.brand} {self.model} can reach {top_speed} km/h")
Creating Object
car1 = Car("Toyota", "White", 180, "Hilux")
car3 = Car("BMW", "Blue", 260, "X5")
car3.start()
car3.stop(4)
car3.acceleration(260)
print(car1.color)
print(car1.make)
Output
The BMW car has started
The BMW car has stopped at 4pm.
The BMW X5 can reach 260 km/h
White
CrossOver SUV
Example2: M-Pesa Account Class
class MpesaAccount:
def __init__(self, name, phone_number, balance):
self.name = name
self.phone_number = phone_number
self.balance = balance
def deposit(self, amount):
self.balance += amount
print(f"Deposited {amount}. New balance: {self.balance}")
def withdrawal(self, amount):
if amount > self.balance:
print("Insufficient funds")
else:
self.balance -= amount
print(f"Withdrew {amount}. New balance: {self.balance}")
def check_balance(self):
print(f"Balance: {self.balance}")
Creating object and usage
alex_account = MpesaAccount("Alex", "+254712345678", 0)
alex_account.deposit(1000)
alex_account.check_balance()
alex_account.withdrawal(500)
Output
Deposited 1000. New balance: 1000
Balance: 1000
Withdrew 500. New balance: 500
3. The Four Pillars of OOP
i. Encapsulation
Protecting data by keeping attributes private and exposing only necessary methods.
Encapsulation means wrapping data and methods into a single unit (the class) and restricting direct access to internal details.
It’s like locking your valuables inside a safe - only authorized methods (keys) can access or modify them.
Key idea in the example below:
Keep attributes private using double underscores (__balance).
Provide public methods (deposit(), withdraw()) to interact safely.
Example
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.__balance = balance # Private attribute
def deposit(self, amount):
if amount > 0:
self.__balance += amount
print(f"Deposited {amount}. New balance: {self.__balance}")
else:
print("Deposit must be positive")
def check_balance(self):
print(f"Balance: {self.__balance}")
Usage
acc = BankAccount("Alex", 3000)
acc.deposit(500)
acc.withdraw(1000)
print(acc.check_balance())
Output
Deposited 500. New balance: 3500
Withdrew 1000. New balance: 2500
2500
Why it matters:
Encapsulation prevents accidental or unauthorized changes to data, ensuring data integrity and security.
ii. Inheritance
Reuse attributes and methods from a parent class.
Inheritance allows one class (child) to reuse and extend the functionality of another class (parent).
It’s like a child inheriting traits from their parents but adding their own personality.
Key idea:
Use super() to call the parent’s constructor.
Add or override methods to customize behavior.
Example
class FarmAnimal:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(f"{self.name} is eating")
Child Class Example
class Cow(FarmAnimal):
def __init__(self, name, age, milk_per_day):
super().__init__(name, age)
self.milk_per_day = milk_per_day
def produce_milk(self):
print(f"{self.name} produces {self.milk_per_day} litres per day")
Usage
mukiri = Cow("Mukiri", 3, 250)
mukiri.eat()
mukiri.produce_milk()
Output
Mukiri is eating
Mukiri produces 250 litres per day
Why it matters:
Inheritance promotes code reuse, reduces duplication, and helps maintain a logical hierarchy - making large systems easier to manage.
iii. Polymorphism- One Interface, Many Forms
Same method name behaves differently depending on the object.
Polymorphism means “many forms” - different objects can respond to the same method call in their own way.
It’s like different musicians playing the same song on different instruments - same melody, unique sound.
Key idea:
Use the same method name across classes.
Each class defines its own version of the method.
Example
class Delivery:
def delivery_status(self):
print("Delivery is processing")
class Motorbike(Delivery):
def delivery_status(self):
print("Delivery is complete")
Usage
d1 = Delivery()
d2 = Motorbike()
d1.delivery_status()
d2.delivery_status()
Output
Delivery is processing
Delivery is complete
Why it matters:
Polymorphism makes code flexible and scalable - you can add new classes without changing existing logic.
iv. Abstraction
Abstraction means showing only what’s necessary and hiding the rest.
It’s like driving a car - you use the steering wheel and pedals without worrying about how the engine works.
Key idea:
Use the abc module and @abstractmethod decorator.
Define abstract methods that must be implemented by child classes.
Example
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Rectangle(Shape):
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
Usage
rect = Rectangle(10, 5)
print(rect.area())
Output
50
Why it matters:
Abstraction simplifies complex systems by exposing only essential features - making code cleaner, easier to use, and less error-prone.
Comparison of the Four Pillars of OOP
| Pillar | Description | Example in Python | Key Benefit |
|---|---|---|---|
| Encapsulation | Restrict direct access to attributes, expose via methods. | Private __balance in BankAccount. |
Protects data integrity. |
| Inheritance | Child class reuses parent’s attributes/methods. |
Cow(FarmAnimal) inherits eat(). |
Promotes code reuse. |
| Polymorphism | Same method behaves differently across classes. |
delivery_status() in Delivery vs Motorbike. |
Increases flexibility. |
| Abstraction | Hide implementation, expose only essentials. |
Shape with abstract area(). |
Simplifies usage. |
Conclusion
Object-Oriented Programming transforms how we structure Python code - from simple scripts to scalable systems.
Top comments (0)