Python Abstract Classes & Dunder Methods

๐Ÿ Python 3.12+ ๐ŸŸข Chapter 33 of 65 ๐Ÿ“‚ Phase 7: Object-Oriented Programming ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: Abstract Base Classes (abc.ABC) ยท @abstractmethod ยท __str__ vs __repr__ ยท __len__ ยท __eq__ ยท Operator Overloading
Master formal interface contracts with Python's abc module and Abstract Base Classes (ABCs), and unlock custom operator behavior with Python Dunder (Magic) Methods like __str__, __repr__, __len__, __eq__, and __add__.
1Abstract Base Classes (ABCs) & Interface Contracts

An Abstract Base Class (ABC) is a blueprint class that defines a common interface contract for a set of subclasses. It cannot be instantiated directly.

Using Python's built-in abc module (ABC and @abstractmethod):

  • Any subclass inheriting from an ABC MUST implement all declared abstract methods.
  • If a subclass forgets to implement an abstract method, Python prevents instantiation at runtime with a TypeError: Can't instantiate abstract class ... with abstract method.
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Abstract Class: DatabaseConnector (ABC) โ”‚ โ”‚ โ”œโ”€โ”€ @abstractmethod connect() โ”‚ โ”‚ โ””โ”€โ”€ @abstractmethod query(sql) โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ [Mandatory Implementation Contract] โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ–ผ โ–ผ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ PostgresConnector โ”‚ โ”‚ MongoConnector โ”‚ โ”‚ โ”œโ”€โ”€ connect() { ... } โ”‚ โ”‚ โ”œโ”€โ”€ connect() { ... } โ”‚ โ”‚ โ””โ”€โ”€ query(sql) { ... } โ”‚ โ”‚ โ””โ”€โ”€ query(sql) { ... } โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
๐Ÿ’ป Example 1: Defining and Enforcing Abstract Base Classes (ABCs)
from abc import ABC, abstractmethod

class NotificationService(ABC):
    """Abstract Base Class defining the notification contract."""
    
    @abstractmethod
    def send(self, recipient, message):
        """Must be implemented by all notification channels!"""
        pass

class EmailNotification(NotificationService):
    def send(self, recipient, message):
        return f"๐Ÿ“ง Sending Email to [{recipient}]: '{message}'"

class SMSNotification(NotificationService):
    def send(self, recipient, message):
        return f"๐Ÿ“ฑ Sending SMS to [{recipient}]: '{message}'"

# 1. Attempting to instantiate the Abstract Base Class fails:
try:
    service = NotificationService()
except TypeError as err:
    print("๐Ÿšซ ABC Instantiation Blocked:", err)

# 2. Concrete subclasses work properly:
services = [EmailNotification(), SMSNotification()]
for s in services:
    print(s.send("balaji@test.com", "Your OTP is 492810"))
๐Ÿ” Architectural Safety:

ABCs guarantee that team members never deploy a half-implemented plugin or driver that crashes in production due to a missing method.

2Representation Dunder Methods: __str__() vs __repr__()

In Python, Dunder (Magic) methods are special methods surrounded by double underscores (__method__) that hook directly into Python's syntax operators:

  • __str__(self): Returns a user-friendly, human-readable string representation (called by print(obj) and str(obj)).
  • __repr__(self): Returns an unambiguous, developer-focused representation showing exact type and parameters, ideally valid Python code to recreate the object (called by interactive REPLs and debugger inspection).
๐Ÿ’ป Example 2: Implementing __str__ and __repr__ for Clean Output
class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = float(price)

    # Human-friendly display string:
    def __str__(self):
        return f"{self.name} (โ‚น{self.price:,.2f})"

    # Unambiguous developer representation:
    def __repr__(self):
        return f"Product(name={self.name!r}, price={self.price})"

item = Product("Mechanical Keyboard", 2499.00)

print("str(item) for Users:    ", str(item))  # Mechanical Keyboard (โ‚น2,499.00)
print("repr(item) for Developers:", repr(item)) # Product(name='Mechanical Keyboard', price=2499.0)
๐Ÿ” Golden Rule of __repr__:

If you only implement one of them, always implement __repr__, because Python will automatically fall back to __repr__ if __str__ is missing.

3Operator Overloading: __len__(), __eq__(), and __add__()

Python allows your custom classes to integrate seamlessly with standard language operators:

  • __len__(): Hooks into len(obj).
  • __eq__(): Hooks into == value comparison.
  • __add__(): Hooks into the + addition operator.
๐Ÿ’ป Example 3: Overloading == and + Operators with Dunder Methods
class Money:
    def __init__(self, amount, currency="INR"):
        self.amount = float(amount)
        self.currency = currency

    def __repr__(self):
        return f"Money({self.amount}, '{self.currency}')"

    def __str__(self):
        return f"โ‚น{self.amount:,.2f} {self.currency}"

    # Overload == operator:
    def __eq__(self, other):
        if isinstance(other, Money):
            return self.amount == other.amount and self.currency == other.currency
        return False

    # Overload + operator:
    def __add__(self, other):
        if not isinstance(other, Money) or self.currency != other.currency:
            raise TypeError("Cannot add money of different currencies!")
        return Money(self.amount + other.amount, self.currency)

# Test operator overloading:
m1 = Money(1500)
m2 = Money(2500)
m3 = Money(1500)

print("m1 + m2 =", m1 + m2)     # Calls __add__ -> โ‚น4,000.00 INR
print("m1 == m3?", m1 == m3)     # Calls __eq__  -> True
print("m1 == m2?", m1 == m2)     # Calls __eq__  -> False
๐Ÿ” Elegant Syntax:

With __add__ and __eq__, your custom objects behave like built-in Python primitives with natural mathematical syntax!

โš ๏ธ Common Developer Pitfall: Returning Non-String Objects from __str__() or __repr__()

The __str__() and __repr__() methods MUST return a string object (str). Returning an integer, list, or printing to the console with print() inside them causes a fatal TypeError: __str__ returned non-string.

๐Ÿ’ป Hands-on Interactive Practice Challenge

Create a ShoppingBag class that holds a list of items. Implement __len__() to return total item count, and __str__() to format the bag contents.

Python 3 Practice Challenge โ–ถ Run in Compiler
class ShoppingBag:
    def __init__(self):
        self.items = []

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

    def __len__(self):
        return len(self.items)

    def __str__(self):
        return f"ShoppingBag with {len(self)} items: {', '.join(self.items)}"

bag = ShoppingBag()
bag.add("Laptop")
bag.add("Mouse")
bag.add("Keyboard")

print(bag)
print("Item count via len():", len(bag))
Run This Challenge in Online Python IDE โ†’
โ“ Frequently Asked Questions (FAQ)

Q What is the difference between an Abstract Class and an Interface in Python?

In Python, there is no separate "interface" keyword. Abstract Base Classes (ABCs) serve as interfaces by defining abstract methods with no body (@abstractmethod), while also allowing partial implementation of shared concrete helper methods.

Q What happens if a subclass does not implement all @abstractmethods?

Python raises TypeError: Can't instantiate abstract class SubClass with abstract method ... when attempting to instantiate the subclass.

Q What is the purpose of __getitem__ and __setitem__?

__getitem__ and __setitem__ allow custom objects to support square-bracket indexing and dictionary-like access: obj[key] and obj[key] = value.

OC
Written by Our Compiler Technical Editorial Team
Reviewed for accuracy & tested on Python 3.12+ runtime ยท Last updated August 2026