Object-Oriented Programming in Python: The Complete 2026 Guide

Master classes, inheritance, polymorphism, and design patterns with practical examples
๐Ÿ Python 3.12+ ยท OOP deep dive ๐Ÿ“š 15 min read ๐Ÿ”„ Updated March 2026
โœ๏ธ By Glenn Junsay Pansensoy โ€ข ๐Ÿ“… March 2, 2026 โ€ข โญ 4.9 (128 reviews)

๐Ÿ“‘ Table of Contents

def what_is_oop():

Object-Oriented Programming (OOP) is a programming paradigm that organizes software design around objects rather than functions and logic. An object is a self-contained entity that contains both data (attributes) and behavior (methods). This approach makes code more modular, reusable, and easier to maintain โ€” especially for large-scale applications.

Python supports OOP with a clean, intuitive syntax. Everything in Python is an object, which means you're already using OOP concepts even when you don't realize it. Let's explore the core pillars that make Python's OOP implementation one of the most flexible and powerful in the programming world.

class CoreConcepts:

The four fundamental principles of OOP in Python work together to create robust, scalable code. Understanding these concepts is crucial for writing professional-grade Python applications.

๐Ÿ”ท Encapsulation

Bundling data and methods within a single unit (class), and controlling access through public/private conventions. Python uses naming conventions like _protected and __private to implement encapsulation.

_single_leading_underscore __double_underscore @property decorator

โฌ†๏ธ Inheritance

Creating new classes based on existing ones, reusing and extending functionality. Python supports multiple inheritance through a sophisticated MRO (Method Resolution Order).

class Child(Parent): super().__init__() MRO

๐Ÿ”„ Polymorphism

Objects of different classes can be treated as objects of a common superclass. Python implements this through duck typing: "If it walks like a duck and quacks like a duck, it's a duck."

method overriding duck typing protocols

๐ŸŽญ Abstraction

Hiding complex implementation details and showing only essential features. Achieved through abstract base classes (ABC) and well-designed interfaces.

from abc import ABC @abstractmethod interfaces

class ClassSyntax:

Here's the basic structure of a Python class with all the essential components. This example demonstrates real-world banking system implementation with proper encapsulation and best practices:

class BankAccount:
    """A simple bank account class demonstrating OOP basics"""
    
    # Class attribute (shared across all instances)
    interest_rate = 0.03
    _total_accounts = 0  # Protected class variable
    
    def __init__(self, owner: str, initial_balance: float = 0):
        """Constructor - initializes instance attributes"""
        self.owner = owner              # Public attribute
        self._balance = initial_balance  # Protected attribute (convention)
        self.__account_id = id(self)     # Private attribute (name mangling)
        BankAccount._total_accounts += 1
    
    # Instance method
    def deposit(self, amount: float) -> float:
        """Add money to the account"""
        if amount > 0:
            self._balance += amount
        return self._balance
    
    # Property decorator - getter (encapsulation)
    @property
    def balance(self) -> float:
        """Read-only balance access"""
        return self._balance
    
    # Class method
    @classmethod
    def from_string(cls, account_data: str):
        """Alternative constructor"""
        owner, balance = account_data.split(',')
        return cls(owner.strip(), float(balance))
    
    # Static method
    @staticmethod
    def validate_amount(amount: float) -> bool:
        """Utility method - doesn't need class or instance"""
        return amount > 0 and amount < 1000000
    
    # Magic method for string representation
    def __str__(self) -> str:
        return f"BankAccount(owner={self.owner}, balance=${self._balance:.2f})"

class InheritanceDemo(SavingsAccount):

Inheritance allows you to create specialized versions of classes. Here's how it works in practice with a real banking example:

class SavingsAccount(BankAccount):  # Inheritance
    """Specialized bank account with interest"""
    
    def __init__(self, owner: str, initial_balance: float = 0, min_balance: float = 100):
        super().__init__(owner, initial_balance)  # Call parent constructor
        self.min_balance = min_balance
        self.interest_rate = BankAccount.interest_rate + 0.01  # Better rate
    
    # Method overriding (polymorphism)
    def withdraw(self, amount: float) -> float:
        """Override with minimum balance check"""
        if self._balance - amount >= self.min_balance:
            self._balance -= amount
        else:
            raise ValueError(f"Cannot go below minimum balance ${self.min_balance}")
        return self._balance
    
    def apply_interest(self) -> float:
        """New method specific to savings accounts"""
        self._balance *= (1 + self.interest_rate)
        return self._balance

# Multiple inheritance example
class PremiumAccount(SavingsAccount, LoanMixin):  # Multiple inheritance
    """Combines features from multiple parents"""
    pass

class MagicMethods:

Python's magic methods (dunder methods) let you define how objects behave with built-in operations. They're the key to writing intuitive, Pythonic classes that integrate seamlessly with the language's features.

Essential Python Magic Methods
Method Purpose Example Usage
__init__(self, ...) Constructor - initializes new instances obj = MyClass()
__str__(self) Human-readable string representation print(obj)
__repr__(self) Developer-friendly representation repr(obj)
__len__(self) Length of container len(obj)
__getitem__(self, key) Indexing/slicing support obj[key]
__eq__(self, other) Equality comparison (==) obj1 == obj2
__lt__(self, other) Less than comparison (<) obj1 < obj2
__enter__/__exit__ Context manager support with obj:
__call__(self, ...) Make object callable like a function obj()
__add__(self, other) Addition operator (+) obj1 + obj2
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    # Operator overloading
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    
    def __sub__(self, other):
        return Vector(self.x - other.x, self.y - other.y)
    
    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)
    
    def __abs__(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5
    
    def __bool__(self):
        return abs(self) > 0

# Usage
v1 = Vector(2, 3)
v2 = Vector(1, 4)
v3 = v1 + v2  # Vector(3, 7) via __add__

class BestPractices:

Writing clean, maintainable OOP code in Python requires following established patterns and conventions. Here are the most important principles to follow:

# Modern Python OOP with dataclasses
from dataclasses import dataclass, field
from typing import List, Optional
from datetime import datetime

@dataclass
class TodoItem:
    title: str
    description: Optional[str] = None
    completed: bool = False
    priority: int = 1
    created_at: datetime = field(default_factory=datetime.now)
    
    def mark_complete(self):
        self.completed = True
    
    def __str__(self):
        status = "โœ…" if self.completed else "โฌœ"
        return f"{status} {self.title} (Priority: {self.priority})"

@dataclass
class TodoList:
    name: str
    items: List[TodoItem] = field(default_factory=list)
    
    def add_item(self, title: str, priority: int = 1, description: str = None):
        self.items.append(TodoItem(title=title, priority=priority, description=description))
    
    def completed_items(self) -> List[TodoItem]:
        return [item for item in self.items if item.completed]
    
    def pending_items(self) -> List[TodoItem]:
        return [item for item in self.items if not item.completed]

class AdvancedPatterns:

Advanced OOP patterns in Python enable sophisticated designs while maintaining readability. These patterns are commonly used in professional Python applications:

๐Ÿญ Factory Pattern

Creating objects without specifying the exact class. Useful when object creation logic is complex or when you need to create different types of objects based on conditions.

@classmethod factory methods abstract factory

๐Ÿ“ฆ Singleton

Ensuring a class has only one instance. Implement via metaclass, module-level variable, or the Borg pattern for shared state.

__new__ override metaclass module singleton

๐Ÿ”Œ Adapter Pattern

Making incompatible interfaces work together. Python's duck typing makes this elegantly simple, often requiring just a wrapper class.

composition wrapper classes interface adaptation

๐Ÿ“ Observer Pattern

Notifying dependent objects of state changes. Great for event-driven systems, GUI programming, and reactive applications.

callbacks property observers event emitters
# Singleton pattern using metaclass
class SingletonMeta(type):
    _instances = {}
    
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

class DatabaseConnection(metaclass=SingletonMeta):
    def __init__(self):
        self.connected = False
        self.connection_pool = []
    
    def connect(self):
        # Connection logic
        self.connected = True
        print("Database connected")
    
    def disconnect(self):
        self.connected = False
        print("Database disconnected")

# Usage - both variables point to the same instance
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2)  # True
๐ŸŽฏ try: master_oop() except: keep_practicing()

This guide covers the essential OOP concepts in Python. Remember that OOP is a tool, not a goal โ€” use it when it makes your code clearer and more maintainable. The best design is the one that solves your problem simply. Practice with real projects, contribute to open source, and always strive to write code that your future self will thank you for.

๐Ÿ“š Related Tutorials

Python Decorators Guide Python Type Hints Async/Await in Python Python Design Patterns

๐Ÿ’ฌ Feedback & Discussion

Was this tutorial helpful? Have questions? Connect with the author: