Language:

Search

Object-Oriented Programming (OOP) in Python — From Basics to Real-World Design

Object-Oriented Programming (OOP) in Python — From Basics to Real-World Design

Object-Oriented Programming (OOP) is one of the most powerful ways to structure Python programs. Instead of writing long scripts, OOP lets you build reusable components—called objects—that combine data and behavior together. This lesson takes you from the very basics of classes and objects all the way to advanced concepts like dataclasses, abstract classes, polymorphism, MRO, and common design patterns.


1) What Is OOP?

OOP is a programming style where you model real-world concepts as objects.

Objects = data (attributes) + behavior (methods)

For example, a Car object may have:

  • Attributes → color, model, speed
  • Methods → start(), accelerate(), stop()

You write the blueprint once — that's the class. Then you create many objects from it.


2) Creating Your First Class & Object


class Car:
    def __init__(self, model, color):
        self.model = model      # instance attribute
        self.color = color

    def drive(self):
        print(f"{self.model} is driving...")

# Creating objects
c1 = Car("Toyota Corolla", "White")
c2 = Car("Honda Civic", "Black")

c1.drive()
c2.drive()

What is happening?

  • class Car: → defines the blueprint
  • __init__ → constructor (runs when object is created)
  • self → refers to the current object

3) Instance Variables vs Class Variables


class Student:
    school = "Geeksters Academy"    # class variable (shared)

    def __init__(self, name, score):
        self.name = name            # instance variable
        self.score = score

s1 = Student("Ali", 90)
s2 = Student("Ammar", 85)

print(s1.school, s2.school)
  • Instance variables = each object has its own
  • Class variables = shared by all objects

4) Instance Methods, Class Methods & Static Methods

a) Instance Method (most common)


class Person:
    def greet(self):
        print("Hello from instance method")

b) Class Method

Used when you want a method that works at class level.


class Person:
    count = 0

    @classmethod
    def get_count(cls):
        return cls.count

c) Static Method

Used for utility/helper functions.


class MathTools:
    @staticmethod
    def add(a, b):
        return a + b

5) String Representation — __str__ & __repr__


class User:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f"User(name={self.name})"

6) Encapsulation — Public, Protected, Private


class BankAccount:
    def __init__(self, balance):
        self._balance = balance      # protected
        self.__pin = "1234"          # private

    def deposit(self, amount):
        self._balance += amount

    def get_balance(self):
        return self._balance
  • public → free to access
  • _protected → internal use
  • __private → name-mangled

7) Inheritance — Reusing Behavior


class Animal:
    def speak(self):
        print("Some sound")

class Dog(Animal):
    def speak(self):
        print("Woof!")   # overriding

8) Polymorphism (Many Forms)


class Cat:
    def speak(self):
        print("Meow")

class Dog:
    def speak(self):
        print("Woof")

for pet in (Cat(), Dog()):
    pet.speak()

Python calls the correct method automatically based on object type.


9) MRO — Method Resolution Order


class A: pass
class B(A): pass
class C(B): pass
print(C.mro())

MRO tells Python which parent to look in first when resolving methods.


10) Abstract Classes & Interfaces (abc)


from abc import ABC, abstractmethod

class Payment(ABC):
    @abstractmethod
    def pay(self, amount):
        pass

class PayPal(Payment):
    def pay(self, amount):
        print("Paid using PayPal")

11) Composition (HAS-A) vs Inheritance (IS-A)

Composition Example


class Engine:
    def start(self):
        print("Engine start")

class Car:
    def __init__(self):
        self.engine = Engine()   # has-a

    def start(self):
        self.engine.start()

12) Dataclasses — Simple Models


from dataclasses import dataclass

@dataclass
class Product:
    name: str
    price: float

p = Product("Laptop", 1200)
print(p)

13) Useful Magic Methods


class Vector:
    def __init__(self, x, y):
        self.x = x; self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)

14) Three Common Design Patterns

1) Singleton


class Singleton:
    _instance = None
    def __new__(cls):
        if not cls._instance:
            cls._instance = super().__new__(cls)
        return cls._instance

2) Factory


class ShapeFactory:
    def get_shape(self, type):
        if type == "circle": return Circle()
        if type == "square": return Square()

3) Strategy Pattern


class JSONStrategy:
    def process(self, data): ...

class XMLStrategy:
    def process(self, data): ...

15) Mini Real-World Project: Tiny Billing System


from dataclasses import dataclass

@dataclass
class Item:
    name: str
    price: float

class Cart:
    def __init__(self):
        self.items = []

    def add(self, item: Item):
        self.items.append(item)

    def total(self):
        return sum(i.price for i in self.items)

cart = Cart()
cart.add(Item("Keyboard", 3000))
cart.add(Item("Mouse", 1500))

print("Total:", cart.total())

Key Takeaways

  • OOP models real-world concepts using classes and objects.
  • __init__ initializes objects; self refers to each instance.
  • Instance methods, class methods, and static methods serve different roles.
  • Inheritance allows code reuse; polymorphism enables flexible behavior.
  • Use abstract classes to define “rules” for subclasses.
  • Prefer composition over inheritance for cleaner design.
  • Magic methods let you customize how objects behave.
  • Dataclasses provide clean, concise models.
  • Design patterns help build scalable applications.

Next up: Modules, CLI Apps & Environment Variables 

Ahmad Ali

Ahmad Ali

Leave a comment

Your email address will not be published. Required fields are marked *

Your experience on this site will be improved by allowing cookies Cookie Policy