Python Abstraction
Learn how to expose only the essential functionality of an object while hiding unnecessary implementation details. You will also learn how Python uses abstract base classes and abstract methods to define clear programming interfaces.
Learning Objectives
By the end of this lesson, you will understand how abstraction helps developers design clear and maintainable object-oriented systems.
You will learn how to:
- Understand the concept of abstraction.
- Distinguish abstraction from encapsulation.
- Understand abstract classes.
- Use Python's
abcmodule. - Use the
@abstractmethoddecorator. - Create abstract base classes.
- Implement abstract methods in child classes.
- Combine abstraction with inheritance.
- Combine abstraction with polymorphism.
- Design flexible application interfaces.
What Is Abstraction?
Abstraction means exposing the important parts of an object while hiding unnecessary implementation details.
In other words, abstraction focuses on:
Consider a car.
When you drive a car, you interact with controls such as the steering wheel, accelerator, brake, and gear selector. You do not need to understand every internal engine calculation in order to drive it.
The interface is simple, while the internal implementation is complex.
start() or process_payment()
while hiding the complicated operations behind them.
Why Abstraction Matters
Software applications can contain thousands or even millions of lines of code.
If every developer or user needed to understand every internal detail, software would become extremely difficult to use and maintain.
Abstraction provides a simpler interface.
payment.process(5000)
The caller does not need to know whether the payment system communicates with a bank, validates a card, creates a transaction record, contacts an API, or generates a receipt.
Those details can remain inside the implementation.
Real-World Abstraction
We use abstraction every day, often without noticing it.
ATM
An ATM provides options such as:
- Withdraw money
- Deposit money
- Check balance
You do not need to understand the internal banking infrastructure.
Web Browser
You enter a URL and the browser handles many internal operations:
- DNS lookup
- Network communication
- HTTP requests
- Response processing
- Rendering
The user interacts with a simple interface.
E-commerce Checkout
A customer may simply click:
Place Order
Behind the button, the application may validate stock, calculate taxes, process payment, create an order, update inventory, and send notifications.
That complexity is hidden behind a simpler interface.
Abstraction vs Encapsulation
These two concepts are closely related but have different purposes.
Abstraction
→ Focuses on what an object does.
→ Hides unnecessary implementation complexity.
Encapsulation
→ Focuses on protecting and controlling object data.
→ Controls how internal state is accessed.
Abstraction = What should the user see?
Encapsulation = How should the internal data be controlled?
A well-designed class can use both principles at the same time.
Abstract Classes
An abstract class is a class designed to act as a blueprint for other classes.
It can define methods that child classes are expected to implement.
Abstract classes are useful when several classes share a common concept but need different implementations.
For example:
Payment
├── CreditCardPayment
├── BankTransfer
└── DigitalWallet
Every payment method should provide a way to process a payment, but each payment system may implement the process differently.
The abc Module
Python provides the abc module for creating
abstract base classes.
abc stands for
Abstract Base Classes.
We can import the required tools using:
from abc import ABC, abstractmethod
ABC provides the base class used to create
abstract classes.
abstractmethod marks a method that child
classes are expected to implement.
The @abstractmethod Decorator
The @abstractmethod decorator tells Python that
a method is required in concrete child classes.
from abc import ABC, abstractmethod
class Payment(ABC):
@abstractmethod
def pay(self, amount):
pass
Here, Payment defines the idea of a payment
operation, but it does not provide a specific payment
implementation.
A concrete child class must implement
pay() before it can be instantiated normally.
Basic Abstract Class
Let's create a simple abstract class for animals.
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self):
pass
The class says:
speak() method.
The abstract class defines the required interface without deciding exactly how every animal should speak.
Implementing Child Classes
Child classes can implement the abstract method in their own way.
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self):
pass
class Dog(Animal):
def speak(self):
print("Woof!")
class Cat(Animal):
def speak(self):
print("Meow!")
dog = Dog()
cat = Cat()
dog.speak()
cat.speak()
Woof!
Meow!
The parent class defines the required behavior, while the child classes provide their implementations.
Multiple Abstract Methods
An abstract class can require multiple methods.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
Any concrete child class must implement both methods.
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
rectangle = Rectangle(10, 5)
print(rectangle.area())
print(rectangle.perimeter())
50
30
Abstract Properties
Abstract classes can also require child classes to provide properties.
from abc import ABC, abstractmethod
class Product(ABC):
@property
@abstractmethod
def price(self):
pass
A concrete child class must provide a compatible
implementation of the price property.
class PhysicalProduct(Product):
def __init__(self, price):
self._price = price
@property
def price(self):
return self._price
product = PhysicalProduct(2500)
print(product.price)
2500
Concrete Methods in Abstract Classes
An abstract class does not have to contain only abstract methods.
It can contain normal, fully implemented methods as well.
from abc import ABC, abstractmethod
class Payment(ABC):
@abstractmethod
def pay(self, amount):
pass
def receipt(self):
print("Payment receipt generated.")
class CardPayment(Payment):
def pay(self, amount):
print(f"Paid ${amount} by card.")
payment = CardPayment()
payment.pay(1000)
payment.receipt()
Paid $1000 by card.
Payment receipt generated.
The child class must implement pay(), but it
automatically inherits the concrete receipt()
method.
Abstraction and Inheritance
Abstract classes are closely connected to inheritance.
The abstract parent establishes the rules or interface, while child classes provide concrete implementations.
Abstract Class
↓
┌─────┼─────┐
↓ ↓ ↓
Class Class Class
A B C
For example:
Payment
↓
CreditCardPayment
BankTransfer
DigitalWallet
Each child follows the same general payment contract while implementing the details differently.
Abstraction and Polymorphism
Abstraction becomes especially powerful when combined with polymorphism.
from abc import ABC, abstractmethod
class Payment(ABC):
@abstractmethod
def pay(self, amount):
pass
class CardPayment(Payment):
def pay(self, amount):
print(f"Card payment: ${amount}")
class BankTransfer(Payment):
def pay(self, amount):
print(f"Bank transfer: ${amount}")
class DigitalWallet(Payment):
def pay(self, amount):
print(f"Digital wallet: ${amount}")
payments = [
CardPayment(),
BankTransfer(),
DigitalWallet()
]
for payment in payments:
payment.pay(500)
Card payment: $500
Bank transfer: $500
Digital wallet: $500
The abstract class establishes the common interface:
pay(amount)
Polymorphism then allows each child class to implement that operation differently.
Real-World Applications
E-commerce Payments
A payment interface can require:
pay(amount)
Different providers can implement it differently.
Notification Services
An abstract notification class might require:
send(message)
Child classes could implement:
- Email notifications
- SMS notifications
- Push notifications
Data Export
A reporting application might define:
export(data)
Different classes could export the same data as:
- CSV
- JSON
- Excel
Database Systems
A common database interface might define operations such as:
connect()
execute()
close()
Different database implementations can provide their own versions.
Benefits and Limitations
Benefits
- Reduces unnecessary complexity.
- Creates clear interfaces.
- Encourages consistent designs.
- Makes large applications easier to maintain.
- Supports polymorphism.
- Makes systems easier to extend.
- Separates interface from implementation.
Limitations
- Too much abstraction can make simple code unnecessarily complicated.
- Abstract interfaces need careful design.
- Beginners may find multiple layers difficult to follow.
- Not every small class requires an abstract base class.
Common Mistakes
1. Thinking Abstract Classes Are Normal Classes
An abstract class is designed to establish a contract or common structure for concrete implementations.
2. Forgetting to Import ABC
You normally need:
from abc import ABC, abstractmethod
3. Forgetting @abstractmethod
Simply creating a method named pay() does not
make it abstract.
4. Not Implementing Required Methods
A concrete child class must implement all inherited abstract methods before it can normally be instantiated.
5. Making Everything Abstract
Not every method needs to be abstract. Shared behavior can often be implemented directly in the abstract base class.
6. Confusing Abstraction with Data Hiding
Abstraction hides unnecessary implementation complexity. Encapsulation focuses more directly on controlling access to internal state.
Practice Exercises
Try these exercises independently before attempting the mini challenge.
Exercise 1 — Animal Interface
Create an abstract Animal class with an
abstract speak() method.
Exercise 2 — Shapes
Create an abstract Shape class requiring
area() and perimeter().
Exercise 3 — Payment System
Create an abstract Payment class with a
pay() method and implement two payment
methods.
Exercise 4 — Notifications
Create an abstract notification class requiring
send().
Exercise 5 — Data Export
Create an abstract exporter with an
export() method and implement CSV and JSON
exporters.
Exercise 6 — Abstract Property
Create an abstract class requiring a
price property.
Exercise 7 — Concrete Method
Add a normal shared method to an abstract base class and demonstrate inheritance.
Exercise 8 — Polymorphic Processing
Create several concrete implementations and process them using one common function.
Mini Challenge — Payment Processing Framework
Your Mission
Build a professional payment framework using abstraction and polymorphism.
Requirements
-
Import
ABCandabstractmethod. -
Create an abstract class called
Payment. -
Add an abstract method called
pay(amount). -
Create
CreditCardPayment. -
Create
BankTransfer. -
Create
DigitalWallet. -
Implement
pay()differently in each class. -
Create a common function called
process_payment(). - Process all payment objects through the same function.
from abc import ABC, abstractmethod
class Payment(ABC):
@abstractmethod
def pay(self, amount):
pass
class CreditCardPayment(Payment):
def pay(self, amount):
print(f"Credit card payment: ${amount}")
class BankTransfer(Payment):
def pay(self, amount):
print(f"Bank transfer payment: ${amount}")
class DigitalWallet(Payment):
def pay(self, amount):
print(f"Digital wallet payment: ${amount}")
def process_payment(payment, amount):
payment.pay(amount)
payments = [
CreditCardPayment(),
BankTransfer(),
DigitalWallet()
]
for payment in payments:
process_payment(payment, 1000)
Credit card payment: $1000
Bank transfer payment: $1000
Digital wallet payment: $1000
CashOnDelivery class without changing
the process_payment() function.
Then add a concrete method to the abstract
Payment class that prints a standard
transaction message.
Quick Knowledge Check
Test your understanding of abstraction.
1. What is abstraction?
2. What does abstraction mainly focus on?
3. Which Python module supports abstract base classes?
4. Which decorator marks a method as abstract?
5. Which class is commonly used as the base for an abstract class?
6. Can an abstract base class contain normal concrete methods?
7. What must a concrete child class normally do?
8. Which concept focuses more directly on controlling access to internal data?
9. What can abstraction and polymorphism provide together?
10. Which is a good reason to use abstraction?
Lesson Summary
Abstraction allows us to expose essential functionality while hiding unnecessary implementation details.
- Abstraction focuses on what an object does rather than how every internal detail works.
- Abstract classes can act as blueprints for concrete child classes.
-
Python's
abcmodule provides tools for abstract base classes. -
ABCcan be used as the base class for an abstract class. -
@abstractmethodmarks methods that concrete subclasses are expected to implement. - Abstract classes can contain both abstract and concrete methods.
- Abstract properties can define required data interfaces.
- Abstraction works naturally with inheritance.
- Abstraction and polymorphism together allow flexible common interfaces with different implementations.
- Encapsulation controls access to internal state, while abstraction hides unnecessary implementation complexity.
Ready to move forward?
Mark this lesson complete after you understand
abstraction, abstract classes, the abc
module, abstract methods, and how abstraction works
with inheritance and polymorphism.