Skip to content

OOP Fundamentals Competent

🐍 Core Python Track · Level 2
⏱️ ~2 weeks 📚 Prerequisite: Modules & Packages

When you'd use this

Classes, inheritance, polymorphism, encapsulation and abstract base classes.

Model entities with state and behavior — domain objects, plugins, stateful services — and use inheritance/polymorphism to share and specialize logic.

Classes & Objects

A class is a blueprint; an object is an instance with its own data. Use classes to bundle related state and behavior — domain entities, services, components.

class Dog:
    species = "Canis familiaris"   # class variable

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

    def bark(self):
        return f"{self.name} says Woof!"

rex = Dog("Rex", 5)
print(rex.bark())        # Rex says Woof!
print(Dog.species)       # Canis familiaris

Inheritance

Derive a subclass that reuses and specializes a base class. Use it for genuine "is-a" relationships; prefer composition when you only want to reuse code.

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

    def speak(self):
        raise NotImplementedError

class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

super()

Call the parent class's implementation — most often to run its __init__ before adding subclass-specific setup.

class Vehicle:
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model

class Car(Vehicle):
    def __init__(self, brand, model, doors):
        super().__init__(brand, model)   # call parent
        self.doors = doors

Encapsulation

Hide internal state behind methods/properties so callers can't put the object in an invalid state. Use a leading _ by convention and @property for validated access.

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

    @property
    def balance(self):
        return self._balance

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

    def withdraw(self, amount):
        if 0 < amount <= self._balance:
            self._balance -= amount

Polymorphism

Different types responding to the same call. Use it to write code against an interface and let each type supply its own behavior — no if type == ... chains.

animals = [Cat("Whiskers"), Dog("Rex")]
for animal in animals:
    print(animal.speak())   # each calls its own version
# Whiskers says Meow!
# Rex says Woof!

Abstract Base Classes

Define an interface subclasses must implement — instantiating an incomplete subclass fails fast. Use for plugin contracts and enforcing a common API.

from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self) -> float:
        pass

    @abstractmethod
    def perimeter(self) -> float:
        pass

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14159 * self.radius ** 2

    def perimeter(self):
        return 2 * 3.14159 * self.radius

Dunder Methods

"Double underscore" hooks let your objects work with built-in syntax — +, ==, len(), iteration, repr(). Implement them so your types feel native.

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

    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

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

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __len__(self):
        return int((self.x**2 + self.y**2) ** 0.5)

v = Vector(1, 2) + Vector(3, 4)
print(v)                       # Vector(4, 6)       — __add__ then __repr__
print(Vector(3, 4) == Vector(3, 4))   # True        — __eq__
print(len(Vector(3, 4)))       # 5                  — __len__ (magnitude)

Practice exercises

  1. Build a Library system with Book, Member and loan tracking.
  2. Create a shape hierarchy with Circle, Rectangle, Triangle all implementing area() and perimeter().
  3. Implement __add__, __sub__, __eq__ for a Money class with currency conversion.
  4. Write an abstract Database class with concrete SQLiteDB and PostgresDB implementations.

💬 Discussion

Have a question about this topic? Found an error? Share your thoughts below.