LearnContact
Lesson 4025 min read

Abstraction

Learn how abstraction hides implementation complexity behind a simple interface, using the abc module, abstract base classes, and @abstractmethod.

Introduction

When you drive a car, you press the accelerator without knowing exactly how fuel injection, combustion, and the transmission work together. The car exposes a simple interface — pedals and a steering wheel — while hiding enormous mechanical complexity underneath. Abstraction brings this same idea to your classes.

In this lesson, you will learn what abstraction means, how Python's abc module lets you define abstract base classes that cannot be instantiated directly, and how @abstractmethod forces subclasses to implement specific methods.

What You Will Learn
  • What abstraction means: hiding complexity behind a simple interface.
  • How to use Python's abc module and the ABC base class.
  • How @abstractmethod forces subclasses to implement required methods.
  • How to build an abstract Shape class with concrete Circle and Square subclasses.
  • How abstraction differs from encapsulation.

What is Abstraction?

Abstraction means exposing only the essential features of an object while hiding the complicated implementation details behind a simple, well-defined interface. Users of a class need to know what a method does, not necessarily how it does it internally.

You already use abstraction constantly: calling len("hello") does not require you to know how Python computes a string's length internally. In your own classes, abstraction is often expressed by defining a common set of methods that every subclass must provide, without dictating exactly how each one is implemented.

Simple Interface

Users interact through a small set of well-named methods.

Hidden Complexity

The internal implementation can be complex, messy, or change entirely without affecting users.

Enforced Contract

Abstract classes can require that subclasses implement specific methods.

The abc Module

Python's built-in abc module (short for "Abstract Base Classes") provides the tools needed to define formal abstract classes: the ABC base class to inherit from, and the @abstractmethod decorator to mark methods that subclasses are required to implement.

import_abc.py
from abc import ABC, abstractmethod
Why Not Just Use a Regular Class?

A regular base class can define methods, but it cannot stop someone from instantiating it directly, and it cannot force subclasses to override anything. ABC and @abstractmethod add both of those guarantees.

Defining an Abstract Base Class

To create an abstract class, inherit from ABC and mark any method that subclasses must implement with @abstractmethod. The method body is typically left empty (or uses pass), since the abstract class only defines the contract, not the implementation.

abstract_shape.py
from abc import ABC, abstractmethod


class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass


# Trying to create a Shape directly fails:
try:
    s = Shape()
except TypeError as e:
    print("Error:", e)
Output
Error: Can't instantiate abstract class Shape with abstract methods area, perimeter

Python refuses to create a Shape instance because Shape has abstract methods that have not been implemented. This enforces that Shape is meant only to be a blueprint for subclasses, not something you use directly.

Implementing Abstract Methods in Subclasses

A subclass of an abstract class must implement every method marked with @abstractmethod before it can be instantiated. Once it does, it becomes a normal, concrete class that behaves just like any other.

concrete_shapes.py
from abc import ABC, abstractmethod


class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass


class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return round(3.1416 * self.radius ** 2, 2)

    def perimeter(self):
        return round(2 * 3.1416 * self.radius, 2)


class Square(Shape):
    def __init__(self, side):
        self.side = side

    def area(self):
        return self.side ** 2

    def perimeter(self):
        return 4 * self.side


shapes = [Circle(3), Square(5)]

for shape in shapes:
    print(f"{shape.__class__.__name__}: area={shape.area()}, perimeter={shape.perimeter()}")
Output
Circle: area=28.27, perimeter=18.85
Square: area=25, perimeter=20
Incomplete Subclasses Still Fail

If Square only implemented area() but not perimeter(), Python would still refuse to instantiate Square, and raise the same "Can't instantiate abstract class" error — every abstract method must be implemented, not just some of them.

Abstraction vs Encapsulation

These two concepts are often confused because both involve "hiding" something, but they hide different things for different reasons.

Abstraction

  • Hides implementation complexity.
  • Focuses on WHAT an object does.
  • Achieved with abstract classes and interfaces (abc module).
  • Concerned with design and structure.

Encapsulation

  • Restricts direct access to internal data.
  • Focuses on HOW data is protected.
  • Achieved with _name, __name, and @property.
  • Concerned with data protection and validation.

In short: abstraction is about designing a clean interface and hiding complex internals, while encapsulation (covered earlier) is about protecting an object's internal state from invalid or unauthorized changes.

Why Abstraction Matters

Enforces Consistency

Every subclass is guaranteed to implement the required methods, so calling code can rely on them existing.

Simplifies Usage

Users of a class work with a small, predictable interface instead of internal implementation details.

Supports Team Development

One developer can define the abstract contract while others implement concrete subclasses independently.

Common Mistakes

Avoid These Mistakes
  • Forgetting to inherit from ABC, which means @abstractmethod has no effect and the class can be instantiated anyway.
  • Leaving an abstract method unimplemented in a subclass and being surprised when Python raises a TypeError.
  • Confusing abstraction with encapsulation — abstraction hides complexity, encapsulation restricts access.
  • Making every class in a codebase abstract "just in case" — abstract classes are useful only when you truly want to enforce a shared contract across multiple subclasses.

Best Practices

  • Use abstract base classes when you have several related classes that must all implement the same set of methods.
  • Keep abstract method bodies minimal (pass or a docstring) — the real logic belongs in subclasses.
  • Name abstract classes after the general concept they represent (Shape, Vehicle, PaymentMethod).
  • Combine abstraction with polymorphism: write code that works with the abstract type and lets any concrete subclass plug in.
  • Do not overuse abstract classes for simple programs with only one implementation — they add value mainly when multiple subclasses share a contract.

Frequently Asked Questions

Can I create an instance of an abstract class directly?

No. Python raises a TypeError if you try to instantiate a class that inherits from ABC and still has unimplemented @abstractmethod methods.

What happens if a subclass does not implement all abstract methods?

The subclass itself becomes abstract too, and Python will refuse to instantiate it until every abstract method from the parent is implemented.

Can an abstract class have regular (non-abstract) methods?

Yes. An abstract class can mix abstract methods that subclasses must implement with regular, fully-implemented methods that subclasses simply inherit and reuse.

Is abstraction the same as an interface in other languages?

It is conceptually very similar. Python does not have a dedicated "interface" keyword like Java, but an ABC with only abstract methods serves the same purpose.

How is abstraction different from encapsulation?

Abstraction hides implementation complexity and focuses on defining what a class should do. Encapsulation restricts direct access to an object's internal data and focuses on protecting how that data is stored and changed.

Key Takeaways

  • Abstraction hides implementation complexity behind a simple, well-defined interface.
  • Python's abc module provides ABC and @abstractmethod to define formal abstract classes.
  • A class inheriting from ABC with unimplemented abstract methods cannot be instantiated.
  • Subclasses must implement every abstract method before they can be instantiated themselves.
  • Abstraction (hiding complexity, defining a contract) is distinct from encapsulation (restricting access to data).

Summary

Abstraction lets you define a clean, consistent interface for a family of related classes while hiding the specific implementation details inside each subclass. Python's abc module, through ABC and @abstractmethod, enforces this contract at the language level, refusing to instantiate incomplete classes.

You have now covered all four pillars of OOP: encapsulation, inheritance, polymorphism, and abstraction. Next, you will learn about magic (dunder) methods — the special methods that let your custom objects integrate naturally with Python's built-in syntax.

Lesson 40 Completed
  • You understand what abstraction means.
  • You can use the abc module, ABC, and @abstractmethod.
  • You can define an abstract class and implement it in concrete subclasses.
  • You can explain the difference between abstraction and encapsulation.
  • You are ready to learn about magic (dunder) methods.
Next Lesson →

Magic (Dunder) Methods