Abstract base classes — ABC module, `@abstractmethod`
WHAT is an ABC?
WHY do we need them?
Two big wins:
- Fail early, fail loud — missing methods are caught at instantiation, not later.
- Self-documenting design — the ABC lists exactly what a subclass owes you.
HOW it works (derivation from first principles)
We don't need to memorise magic — we can build up the behaviour.
Step 1 — A plain base class does NOT enforce anything.
class Shape:
def area(self):
raise NotImplementedError # only fails when CALLEDWhy this step? This is the "poor man's ABC". The error only fires when someone actually calls area(). You can still create Shape() and pass it around — the bomb is hidden.
Step 2 — Inherit from ABC + mark the method abstract.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
...Why this step? ABC uses a special metaclass (ABCMeta). When you try Shape(), the metaclass checks an internal set called __abstractmethods__. If it is non-empty, instantiation is blocked immediately.
Step 3 — Watch the enforcement.
Shape() # TypeError: Can't instantiate abstract class Shape
# with abstract method areaWhy this step? The error now happens at construction time and names the missing method. That's the whole point.
Step 4 — A concrete subclass clears the contract.
class Circle(Shape):
def __init__(self, r):
self.r = r
def area(self):
return 3.14159 * self.r ** 2
Circle(2).area() # 12.566 ✅ worksWhy this step? Once Circle overrides area, its __abstractmethods__ set is empty → instantiation allowed.

The mechanism in one sentence
__abstractmethods__ is a frozenset computed automatically by ABCMeta every time a class is defined. Inherited-but-unimplemented abstract methods stay in the set; overridden ones are removed.
Going deeper: combining decorators
Worked example: a payment system
from abc import ABC, abstractmethod
class PaymentProcessor(ABC):
@abstractmethod
def pay(self, amount): ...
@abstractmethod
def refund(self, amount): ...
class CardProcessor(PaymentProcessor):
def pay(self, amount): return f"Charged {amount} to card"
def refund(self, amount): return f"Refunded {amount} to card"Why two abstract methods? The contract says "any processor must both pay AND refund." If CardProcessor only defines pay, __abstractmethods__ still contains refund, so CardProcessor(...) raises TypeError. Step-by-step why: the metaclass subtracts implemented names from the inherited abstract set; refund survives → set non-empty → blocked.
def checkout(p: PaymentProcessor, amt):
return p.pay(amt) # safe: ANY subclass guarantees pay() existsWhy this is safe: the type hint + ABC contract means every object reaching checkout provably has pay. No defensive hasattr needed.
Common mistakes (Steel-man each)
Recall Feynman: explain to a 12-year-old
Imagine a fill-in-the-blanks worksheet for building a toy. The worksheet says: "Every robot MUST have a walk() button and a talk() button." It's not a finished robot — you can't play with the worksheet itself. Anyone who wants to make a real robot has to fill in BOTH buttons. If they forget the talk() button, the factory refuses to build their robot and tells them exactly which button is missing — before it leaves the factory, not after a kid presses it and nothing happens. The worksheet = abstract base class. The "MUST have" buttons = @abstractmethod. The factory check = __abstractmethods__ must be empty.
Forecast-then-Verify
Flashcards
What two ingredients make a class abstract in Python?
ABC (or metaclass=ABCMeta) AND decorate ≥1 method with @abstractmethod.When does instantiating an abstract class fail?
TypeError), the moment you call ClassName(), not when a method is later called.What attribute determines if a class can be instantiated?
__abstractmethods__ — a frozenset; instantiation allowed only if it's empty.Does @abstractmethod alone (without inheriting ABC) enforce anything?
ABCMeta.How does a subclass satisfy the contract?
Correct decorator order for an abstract property?
@property on top, @abstractmethod directly above def (abstractmethod innermost).Can an abstract method contain real code?
super().method().Does Python's ABC check that overriding methods have matching signatures?
What error message do you get instantiating an abstract class?
Connections
- Inheritance and Method Overriding — ABCs rely on overriding to clear the contract.
- Polymorphism — ABCs guarantee a common interface so polymorphic calls are safe.
- Duck Typing vs Nominal Typing — ABCs add nominal (declared) typing on top of duck typing.
- Interfaces in other languages — Java
interface/ C++ pure virtual= 0are the analogues. - Metaclasses and ABCMeta — the machinery that powers
__abstractmethods__. - Protocols (typing.Protocol) — structural alternative to nominal ABCs.
Concept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Dekho, abstract base class (ABC) ek aisa class hai jise tum directly object banane ke liye use nahi kar sakte — ye sirf ek blueprint ya contract hai. Tum from abc import ABC, abstractmethod import karte ho, apne class ko ABC se inherit karwaate ho, aur jo methods har subclass ko zaroor banane chahiye unke upar @abstractmethod laga dete ho. Bas — ab Python guarantee karta hai ki koi bhi object tab tak nahi banega jab tak saare abstract methods override na ho jaayein.
Iska faayda kya hai? Maan lo tum ek function likh rahe ho jo har Shape pe area() call karta hai. Agar kisi ne Triangle banaya aur area() likhna bhool gaya, to bina ABC ke tumhe error bahut baad mein milega — runtime pe, andar kahin, confusing AttributeError ke saath. ABC ke saath ye error object banate hi turant aa jaata hai, saaf-saaf bata kar ki "bhai, area method missing hai." Matlab bug aage aa gaya, jaldi pakda gaya — yahi hai fail early, fail loud.
Andar ka jugaad simple hai: ABCMeta ek set rakhta hai __abstractmethods__. Jab tak ye set empty nahi hota, class instantiate nahi hoti. Jaise hi subclass saare methods override kar deta hai, set khaali ho jaata hai aur object ban-ne lagta hai. Do galtiyaan yaad rakhna: (1) sirf @abstractmethod lagane se kuch nahi hota agar tumne ABC inherit nahi kiya, aur (2) @property ke saath use karte waqt @abstractmethod ko sabse neeche (innermost) rakhna. Mnemonic: "ABC = A Blueprint Cannot-build" — blanks bharo, tabhi build hoga.