Interfaces: Design Consistent Behaviors Across Classes
Introduction
In this chapter, you will learn how to model interface-style design in Python. Although Python does not have a separate interface keyword like some languages, you can still define clear behavior contracts using abstract base classes. This helps different classes follow the same rules while keeping implementations flexible.
Prerequisites
- Python
3.10+installed - Basic understanding of classes, inheritance, and abstract classes
- Ability to run
.pyfiles in terminal or IDE
What Is an Interface (Conceptually)
An interface defines what a class must do, not how it does it.
Think of it like:
- Power socket standard: devices must follow connector rules
- Different device internals are allowed, as long as interface is respected
In Python, interface-like contracts are often implemented with:
ABC@abstractmethod
1) Create an Interface-Style Contract
Use an abstract class to define required methods.
# Import interface tools
from abc import ABC, abstractmethod
# Interface-style base class
class Notifier(ABC):
@abstractmethod
def send(self, message):
passAny concrete notifier class must implement send().
2) Implement the Interface in Multiple Classes
Different classes can implement the same contract differently.
# Import interface tools
from abc import ABC, abstractmethod
# Interface-style base class
class Notifier(ABC):
@abstractmethod
def send(self, message):
pass
# Email implementation
class EmailNotifier(Notifier):
def send(self, message):
print(f"[Email] {message}")
# SMS implementation
class SMSNotifier(Notifier):
def send(self, message):
print(f"[SMS] {message}")
# Use implementations
email = EmailNotifier()
sms = SMSNotifier()
email.send("Welcome!")
sms.send("Verification code: 1234")Same method name, different behavior.
3) Polymorphism with Interface Contract
You can treat all implementations uniformly.
# Collect different notifier objects
notifiers = [EmailNotifier(), SMSNotifier()]
# Polymorphic call
for notifier in notifiers:
notifier.send("System maintenance at 8 PM.")This is one of the biggest benefits of interface-oriented design.
Tip
Design Benefit
When new notifier types are added later (for example PushNotifier), existing calling code usually stays unchanged.
4) Optional Shared Logic in Interface-Style Base
You can include concrete helper methods in the abstract base class.
# Import interface tools
from abc import ABC, abstractmethod
# Interface-style base class
class PaymentProcessor(ABC):
@abstractmethod
def pay(self, amount):
pass
def validate_amount(self, amount):
return amount > 0
# Concrete implementation
class WeChatPay(PaymentProcessor):
def pay(self, amount):
if self.validate_amount(amount):
print(f"WeChat Pay success: {amount}")
else:
print("Invalid amount.")This avoids repeating common validation logic in every child class.
5) Real Mini Example: Exporter Interface
This example creates a common export contract for multiple formats.
# Import interface tools
from abc import ABC, abstractmethod
# Exporter interface-style class
class DataExporter(ABC):
@abstractmethod
def export(self, data):
pass
# CSV exporter
class CSVExporter(DataExporter):
def export(self, data):
print(f"Exporting to CSV: {data}")
# JSON exporter
class JSONExporter(DataExporter):
def export(self, data):
print(f"Exporting to JSON: {data}")
# Client code
def run_export(exporter, data):
exporter.export(data)
# Test exporters
records = [{"name": "Emma", "score": 95}]
run_export(CSVExporter(), records)
run_export(JSONExporter(), records)This pattern appears often in plugins, storage layers, and service adapters.
Warning
Do not confuse "duck typing" and "interface-style contract."
Duck typing is flexible and implicit; abstract contracts are explicit and stricter.
Common Beginner Mistakes
Mistake 1: Forgetting to Implement Required Methods
If an abstract method is missing in child class, instantiation fails.
Mistake 2: Using Interface-Style Design for Tiny One-Class Scripts
For very small scripts, this can add unnecessary complexity.
Mistake 3: Putting Too Much Business Logic in the Contract Class
Keep abstract base classes focused on shared contract and minimal shared helpers.
Surprise Practice Challenge
Build a "Login Strategy Interface":
- Create abstract class
LoginProviderwithlogin(username, password) - Implement
EmailLoginProvider - Implement
PhoneLoginProvider - Put providers in a list and call
login()on each - Add one shared helper method in the base class (for example
mask_username)
If you finish this, you are designing extensible architecture patterns used in production systems.
FAQ
Does Python have a real interface keyword?
No. Python usually models interfaces with abstract base classes and abstract methods.
When should I use interface-style design?
Use it when multiple classes should follow the same behavior contract.
Is duck typing enough in Python?
Sometimes yes, especially for small or dynamic code. For larger projects, explicit contracts can improve maintainability.
Can one class implement multiple interface-style contracts?
Yes. With multiple inheritance and careful design, a class can satisfy multiple contracts.