AiTechWorlds
AiTechWorlds
Imagine you are the chief architect of a city. Before a single hospital is built, you draft a blueprint. That blueprint defines everything a hospital should have: an emergency room, operating theatres, a pharmacy, a reception desk. It describes what a hospital is — but it is not a hospital itself.
When the city decides to build three hospitals — one downtown, one in the suburbs, one near the airport — each is constructed from that same blueprint. Yet each hospital is its own physical reality: different address, different roster of doctors, different patients checked in today. The blueprint is shared; the buildings are individual.
This is the central idea of Object-Oriented Programming. The blueprint is a class. Each hospital built from it is an object (also called an instance). Every object follows the same structure defined by the class, but carries its own data.
Object-Oriented Programming (OOP) is a programming paradigm that organises code around objects — bundles of data and the functions that operate on that data — rather than around sequences of instructions.
A paradigm is simply a style or way of thinking about how to write programs.
The older alternative is procedural programming, where you write a series of step-by-step instructions and pass data around as separate variables. OOP keeps data and behaviour together in one logical unit.
| Pillar | One-Line Definition |
|---|---|
| Encapsulation | Bundle data and methods together; control who can access the data. |
| Inheritance | A new class can reuse and extend the behaviour of an existing class. |
| Polymorphism | Different objects can respond to the same method call in their own way. |
| Abstraction | Hide complex implementation details; expose only what is necessary. |
You will explore each pillar in depth in later lessons. For now, keep the table as a mental map.
Problem: Model a bank account that can deposit, withdraw, and show a balance.
# Procedural approach — data and logic are separate
balance = 0.0
def deposit(amount):
global balance # Must reach for the global variable
balance += amount
def withdraw(amount):
global balance
if amount <= balance:
balance -= amount
else:
print("Insufficient funds")
def show_balance():
print(f"Balance: ${balance:.2f}")
deposit(500)
withdraw(200)
show_balance()
Output:
Balance: $300.00
The logic works, but the balance variable is floating free. Any part of the program can accidentally set balance = -9999 and nothing will stop it.
# OOP approach — data and logic live together inside the class
class BankAccount:
def __init__(self, owner):
self.owner = owner # Each account has its own owner
self.balance = 0.0 # Each account has its own balance
def deposit(self, amount):
self.balance += amount # Operates on THIS account's balance
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
else:
print("Insufficient funds")
def show_balance(self):
print(f"{self.owner}'s balance: ${self.balance:.2f}")
account = BankAccount("Alice") # Create an object from the class
account.deposit(500)
account.withdraw(200)
account.show_balance()
Output:
Alice's balance: $300.00
Now the balance belongs to the account object. You can create a second account for Bob and both exist independently without any global variable collision.
Line-by-line explanation:
class BankAccount: — defines the blueprint named BankAccountdef __init__(self, owner): — the constructor, called automatically when you create an object; self always refers to the specific object being createdself.owner = owner — stores the owner value as an attribute of this particular objectaccount = BankAccount("Alice") — builds one object (instance) from the blueprintaccount.deposit(500) — calls the deposit method on Alice's account only| Situation | Best Approach |
|---|---|
| Modelling real-world entities (users, products, vehicles) | OOP |
| Multiple objects of the same kind with varying data | OOP |
| A simple 20-line script that runs once | Procedural |
| A configuration file reader | Procedural or functional |
| A large system with many interacting components | OOP |
| A quick data-transformation pipeline | Functional / procedural |
OOP shines when your program models things — entities that have state (data) and behaviour (actions). It becomes overhead when you just need to transform some data and move on.
class Dog: # This is the blueprint (class)
def __init__(self, name, breed):
self.name = breed
self.breed = breed
def bark(self):
print(f"{self.name} says: Woof!")
rex = Dog("Rex", "Labrador") # rex is one object (instance)
bella = Dog("Bella", "Poodle") # bella is a completely separate object
rex.bark() # Rex says: Woof!
bella.bark() # Bella says: Woof!
Both rex and bella are built from the same Dog class, but they are independent objects with their own data. Changing rex.name has zero effect on bella.
| Year | Milestone |
|---|---|
| 1967 | Simula 67 (Norway) — first language with classes and objects |
| 1972 | Smalltalk (Xerox PARC) — first fully OOP language; everything is an object |
| 1985 | C++ — added OOP features to the C language |
| 1995 | Java — OOP as the primary paradigm; "write once, run anywhere" |
| 1991 | Python created; OOP available but optional — you choose when to use it |
Python's flexibility is noteworthy: it supports procedural, OOP, and functional styles. You are not forced into OOP, which means when you do use it, you are choosing it because it genuinely fits the problem.
Get this course's notes on Telegram!
Free cheat sheets, summaries & practice exercises