Skip to main content
Once you’re comfortable with basic classes, Python’s advanced OOP features let you build robust, framework-quality code. You’ll learn how to define interfaces that subclasses must implement, how to make your objects behave like built-in Python types, and how to squeeze out memory savings with __slots__.

Abstract Base Classes

An Abstract Base Class (ABC) defines a set of methods that every subclass must implement. If a subclass fails to implement all abstract methods, Python raises a TypeError the moment you try to instantiate it. This is how you enforce a shared interface across a family of related classes.

Implementing the ABC

Multiple Inheritance and MRO

Python supports multiple inheritance — a class can inherit from more than one parent. When a method is called, Python searches parent classes in a specific order defined by the Method Resolution Order (MRO), computed using the C3 linearisation algorithm.
Use super() to call the next class in the MRO chain rather than hardcoding a parent name:
Multiple inheritance increases complexity quickly. Reserve it for mixin patterns — small, focused classes that add one specific behaviour (e.g., LogMixin, SerializableMixin). Avoid deep or diamond inheritance hierarchies.

Dunder (Magic) Methods

Dunder methods (double-underscore, e.g., __str__) let your objects plug into Python’s built-in syntax and functions. Implementing them makes your classes feel like native Python types.
__str__ controls the human-readable string (str(obj), print(obj)). __repr__ controls the developer-readable string (repr(obj), shown in the REPL).
Make your object behave like a sequence or container.
Control how objects are compared with ==, <, >, etc.
Make an instance callable like a function by implementing __call__.

__slots__ for Memory Optimisation

By default, Python stores each instance’s attributes in a __dict__ dictionary — flexible but memory-heavy. When you declare __slots__, Python uses a fixed-size array instead, which cuts per-instance memory by roughly 40–50% and speeds up attribute access.
__slots__ prevents adding arbitrary attributes to instances at runtime. Use it when you create many instances of a small, fixed-schema class — for example, points in a geometry engine, rows in a data pipeline, or nodes in a graph.

Putting It All Together: a Shape Hierarchy