🐍 Python Course · Stage 1 · Lesson 19 of 89 · Abstract Base Classes
Course Overview →

🟩 Start with the Beginner tab. Read it fully before moving on.

← Enums Data Model →
thecodex.expert · The Codex Family of Knowledge
Python

Abstract Base Classes (abc) in Python

An abstract base class defines an interface that subclasses must implement — Python’s way of declaring "every subclass must provide these methods" and enforcing it at instantiation time.

Python 3.13 docs.python.org Last verified:
Canonical Definition

An abstract base class (ABC), provided by the abc module, is a class that cannot be instantiated directly and may declare abstract methods that concrete subclasses are required to override. Defined in PEP 3119, ABCs formalise interfaces and enable isinstance() checks against capabilities.

🟩 Beginner

Contracts for subclasses

What you will learn: what an abstract base class is, how @abstractmethod forces subclasses to implement methods, and why the error helpfully fires at instantiation time.

How to read this tab: Try creating an incomplete subclass and watch the TypeError appear the moment you instantiate it.

⏱ 25 min📄 1 section🔶 Prerequisite: Object-Oriented Python
The idea

An abstract base class is a contract. It says "any class that claims to be one of these must provide these specific methods." Python refuses to create an object from a class that hasn't fulfilled the contract — so mistakes are caught immediately, not deep in your program.

The error happens at instantiation — exactly when you want it. Defining an incomplete subclass is allowed; the TypeError fires the moment you try to create an instance. You can never accidentally pass around an object missing required methods.

The problem ABCs solve

Without an ABC, nothing stops you from creating an incomplete subclass and only discovering the missing method when it is called — possibly much later, in production. An ABC moves that error to the moment of object creation.

Pythonwhy_abc.py
from abc import ABC, abstractmethod

class Shape(ABC):                 # inherit from ABC
    @abstractmethod
    def area(self):
        ...                       # no implementation — subclasses must provide it

    @abstractmethod
    def perimeter(self):
        ...

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

c = Circle(5)         # works — both methods implemented
print(c.area())       # 78.53...

# You cannot instantiate the ABC itself
# Shape()   # TypeError: Can't instantiate abstract class Shape

# A subclass that forgets a method also can't be instantiated
class Square(Shape):
    def area(self):
        return 4
    # forgot perimeter()
# Square()  # TypeError: Can't instantiate abstract class Square
#           # with abstract method perimeter
The error happens at instantiation, not definition

Defining an incomplete subclass is allowed; the TypeError fires the moment you try to create an instance. This is exactly when you want it — you cannot accidentally pass around an object that is missing required methods.

✅ Beginner tab complete

  • I can define an ABC with @abstractmethod
  • I know an ABC cannot be instantiated directly
  • I know a subclass missing an abstract method cannot be instantiated
  • I know the error fires at instantiation, not definition

Continue to Data Model →

🔵 Intermediate

Abstract properties, partial implementations, virtual subclasses

What you will learn: abstract properties, ABCs that mix concrete and abstract methods, and register() for virtual subclasses.

How to read this tab: Note that register() makes isinstance pass but does NOT enforce the methods — it is a promise.

⏱ 30 min📄 2 sections🔶 Prerequisite: Beginner tab
💡

ABCs can provide working methods too. An ABC is not all-or-nothing — it can mix abstract methods (subclasses must implement) with concrete methods (inherited as-is). This lets you build a base that does the shared work and only requires subclasses to fill specific gaps.

Abstract properties and partial implementations

ABCs can declare abstract properties and can also provide concrete (working) methods alongside abstract ones — giving subclasses a base to build on while still enforcing the required pieces.

Pythonabstract_properties.py
from abc import ABC, abstractmethod

class Employee(ABC):
    def __init__(self, name):
        self.name = name

    @property
    @abstractmethod
    def monthly_salary(self):
        ...                       # abstract property — must be overridden

    @abstractmethod
    def role(self):
        ...

    def annual_salary(self):      # CONCRETE method — inherited as-is
        return self.monthly_salary * 12

    def describe(self):           # concrete, uses abstract methods
        return f"{self.name} ({self.role()}): {self.annual_salary()}/yr"

class Manager(Employee):
    @property
    def monthly_salary(self):
        return 150_000
    def role(self):
        return "Manager"

m = Manager("Priya")
print(m.annual_salary())   # 1800000 — concrete method works
print(m.describe())        # Priya (Manager): 1800000/yr

register() is a promise, not a check. It makes isinstance/issubclass return True without the class inheriting — useful for retrofitting interfaces onto third-party classes. But unlike real inheritance, it does NOT verify the required methods exist. The guarantee is yours to keep.

Virtual subclasses with register()

An ABC can recognise a class as a subclass without that class inheriting from it — via register(). This is how Python lets unrelated classes satisfy an interface, the basis of "duck typing made checkable."

Pythonregister.py
from abc import ABC

class Serialisable(ABC):
    @abstractmethod
    def to_json(self): ...

# An existing class we don't want to (or can't) modify
class LegacyRecord:
    def to_json(self):
        return "{}"

# Register it as a virtual subclass
Serialisable.register(LegacyRecord)

print(issubclass(LegacyRecord, Serialisable))  # True
print(isinstance(LegacyRecord(), Serialisable)) # True
# NOTE: register() does NOT enforce the methods exist — it's a promise.
# Use it for retrofitting interfaces onto existing/third-party classes.

# __subclasshook__ — recognise ANY class with the right method
class Sized(ABC):
    @classmethod
    def __subclasshook__(cls, C):
        if cls is Sized:
            if any("__len__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

print(issubclass(list, Sized))   # True — list has __len__
Commonly confused
ABC vs Protocol. An ABC uses nominal typing — a class must inherit (or be registered) to count. A Protocol (PEP 544) uses structural typing — any class with the right methods counts, no inheritance needed. Use ABC when you want enforcement at instantiation; use Protocol for static duck typing checked by type checkers.
register() does not enforce. Unlike inheriting from an ABC, register() makes isinstance return True but does NOT check that the methods actually exist. It is a promise you make, not a guarantee Python verifies.

✅ Intermediate tab complete

  • I can declare an abstract property
  • I can mix concrete methods with abstract ones in an ABC
  • I can register a virtual subclass with ABC.register()
  • I know register() does not verify the methods exist

Continue to Data Model →

🔴 Expert

ABCMeta, collections.abc, and free mixin methods

What you will learn: how ABCMeta overrides isinstance/issubclass, the collections.abc container ABCs, and the mixin methods you get for free.

How to read this tab: Inherit from collections.abc.Sequence and implement just two methods to get six more automatically.

⏱ 20 min📄 1 section🔶 Prerequisite: After Stage 2

collections.abc and the ABCMeta machinery

ABCs are implemented through the ABCMeta metaclass. When a class uses ABCMeta (which ABC does via inheritance), the metaclass tracks abstract methods in __abstractmethods__ and overrides __instancecheck__ and __subclasscheck__ so that isinstance and issubclass consult registered virtual subclasses and __subclasshook__. The standard library ships a complete set of ABCs in collections.abc describing Python's container protocols.

Pythoncollections_abc.py
from collections.abc import (
    Iterable, Iterator, Sequence, MutableSequence,
    Mapping, MutableMapping, Set, Hashable, Callable
)

# These ABCs let you check capabilities, not concrete types
print(isinstance([], Sequence))        # True
print(isinstance({}, Mapping))         # True
print(isinstance("abc", Iterable))     # True
print(isinstance(len, Callable))       # True
print(isinstance(42, Hashable))        # True

# Inheriting from a collections.abc ABC gives you mixin methods free
class MyList(Sequence):
    def __init__(self, data):
        self._data = data
    def __getitem__(self, i):
        return self._data[i]
    def __len__(self):
        return len(self._data)
    # Sequence provides __contains__, __iter__, __reversed__,
    # index(), and count() automatically from these two methods

ml = MyList([10, 20, 30])
print(20 in ml)          # True  — __contains__ provided by Sequence
print(list(reversed(ml)))# [30,20,10] — __reversed__ provided
print(ml.index(20))      # 1 — index() provided

# __abstractmethods__ holds the set still needing implementation
from abc import ABC, abstractmethod
class Base(ABC):
    @abstractmethod
    def foo(self): ...
print(Base.__abstractmethods__)   # frozenset({'foo'})

The mixin behaviour is the practical payoff: inherit from collections.abc.Sequence and implement just __getitem__ and __len__, and you get __contains__, __iter__, __reversed__, index, and count for free. This is why building custom containers on the collections.abc ABCs is far less work than implementing every protocol method by hand.

✅ Expert tab complete

  • I know collections.abc defines Iterable, Sequence, Mapping, etc.
  • I know inheriting from Sequence gives __contains__/__iter__/index/count free
  • I know __subclasshook__ can recognise any class with the right methods

Continue to Data Model →

Sources

1
Python Standard Library — abc (Abstract Base Classes). docs.python.org/3/library/abc.html.
2
Python Standard Library — collections.abc. docs.python.org/3/library/collections.abc.html.
3
PEP 3119 — Introducing Abstract Base Classes. peps.python.org/pep-3119/.
4
PEP 544 — Protocols: Structural subtyping (contrast with ABCs). peps.python.org/pep-0544/.
Source confidence: High Last verified: Primary source: Python abc module (PEP 3119)