Python

P
PythonHub
Progress 0%

Python

  • Home
  • History of Python
  • Applications of Python
  • Introduction To Python
    • What is Python
    • Character Set
    • Tokens in Python
    • Python Execution Mode
    • Variable And Identifiers
    • Data Types in Python
    • Operators And Expressions
    • Constants in Python
    • Assignment Statement
    • Input / Output in Python
    • Simple Python Scripts
    • Namespace in Python
    • πŸ“ Assignments
  • Operators in Python
    • Arithmetic Operators
    • Assignment Operators
    • Shorthand Assignment Operators
    • Relational Operators
    • Logical Operators
    • Bitwise Operators
    • Special Operators
    • πŸ“ Assignments
  • Input Output in Python
    • Accept Input
    • Output Formatting
    • πŸ“ Assignments
  • Conditional Statement
    • Decision Making
    • if Statement
    • IF-ELSE STATEMENT
    • IF-ELSE LADDER
    • NESTED IF-ELSE
    • Short Hand IF-ELSE
    • πŸ“ Assignments
  • Loops
    • Introduction to Loops
    • While Loop
    • Nested While Loop
    • πŸ“ While Loop Assignments
    • For Loop
    • For Loop Examples
    • Nested For Loop
    • Nested For Loop Examples
    • Infinite While Loops
    • Infinite For Loops
    • Break, Continue and Else in Loops
    • Difference Between For and While Loop
    • For Each Loop
    • πŸ“ For Each Assignments
    • πŸ“ All Loops Assignments
  • List
    • List in Python
    • Access List Elements
    • List Functions
    • Iterate (Loop) List
    • List Comprehension
    • πŸ“ Assignments
  • Tuple
    • Tuple in Python
    • Access Tuple Elements
    • Tuple Functions
    • Iterate (Loop) Tuple
    • Unpack Tuple
    • Tuple Comprehension
    • πŸ“ Assignments
  • Set
    • Set in Python
    • Access Set Elements
    • Set Methods
    • Iterate (Loop) Set
    • Pack/Unpack Set
    • Set Comprehension
    • πŸ“ Assignments
  • Dictionary
    • Dictionary
    • Access Dictionary Items
    • Dictionary Methods
    • Iterate (Loop) Dictionary
    • Formatting Dictionaries
    • Nested Dictionaries
    • Dictionary Comprehension
    • πŸ“ Assignments
  • Diff List Tuple Set Dictionary
    • List vs Tuple
    • List vs Set
    • List vs Dictionary
    • Tuple vs Set
    • Tuple vs Dictionary
    • Dictionary vs Set
    • πŸ“ Assignments
  • Exception
    • Error vs Exception
    • Types of Exception
    • Exception Handling
    • User Defined Exception
    • Logging Exception
    • πŸ“ Assignments
  • Functions
    • Introduction to Functions
    • Modular Programming
    • Types of Functions
    • Inbuilt Functions
    • Need For User-Defined Function
    • Elements of User Defined Function
    • Function Arguments
    • Nesting of Functions
    • Recursion
    • Global Local and Non Local
    • Python Lambda Functions
    • πŸ“ Assignments
  • Python Module
    • Introduction to Module
    • Inbuilt Modules in Python
    • User Defined Module
    • πŸ“ Assignments
  • File Handling
    • Introduction to Files
    • Create File
    • Read Files
    • Write to File
    • Rename File
    • Copy File
    • Move File
    • List Files in Directory
    • Binary Files
    • Zipping and Unzipping Files
    • πŸ“ Assignments
  • Strings
    • Basics of Strings
    • String Special Operators
    • String Formatting Operators
    • String Methods
    • πŸ“ Assignments
  • Regular Expressions
  • Python OOPS
    • Basics of Object Oriented
    • What are Classes and Objects?
    • Creating Class and Object
    • OOP vs Procedural Programming
    • Difference Between Classes and Objects
    • Constructors
    • Destructor
    • Built Class Methods and Attributes
    • Class and Instance Variables
    • Inheritance in Python
    • Single Inheritance
    • Multiple Inheritance
    • Multilevel Inheritance
    • Hierarchical Inheritance
    • Hybrid Inheritance
    • Abstraction
    • Method Overriding
    • Abstract Method
    • Interfaces in Python
    • Abstract Class vs Interface
    • Public, Private and Protected
    • Overloading vs Overriding
    • Inheritance vs Composition
    • Encapsulation
    • Polymorphism
    • Inner Classes
    • πŸ“ Assignments
  • Advanced Python
    • Iterator in Python
    • Generator in Python
    • Decorator in Python
    • Type Hints in Python
    • Async/Await Programming
    • Dataclasses in Python
    • Context Managers in Python
    • Property Decorator in Python
    • __slots__ in Python
    • Enums in Python
    • Walrus Operator in Python
    • Match-Case in Python
    • πŸ“ Assignments
  • Python Standard Library
    • Collections Module
    • Itertools Module
    • Functools Module
    • Datetime Module
    • JSON Module
    • OS Module
    • Sys Module
    • Random Module
    • Math Module
    • πŸ“ Assignments
  • Python Testing
    • Unit Testing in Python
    • Pytest Framework
    • Mocking in Python
    • πŸ“ Assignments
  • Python Best Practices
    • PEP 8 Style Guide
    • Docstrings in Python
    • Logging in Python
    • Code Optimization Tips
    • Debugging Techniques
    • πŸ“ Assignments
  • MySQL Database in Python
    • Introduction to MySQL with Python
    • DBMS vs File System
    • Connecting to MySQL Database
    • Create Database in MySQL
    • Create Table in MySQL
    • Insert Data in MySQL
    • Insert Multiple Rows
    • Select Data from MySQL
    • WHERE Clause in MySQL
    • Update Data in MySQL
    • Delete Data from MySQL
    • Parameterized Queries
    • Transaction Management
    • Error Handling
    • Connection Pooling
    • MySQL Drivers Guide
    • Joins in MySQL
    • Aggregation Functions
    • Backup MySQL Database
    • Best Practices
    • πŸ“ Assignments
  • MySQL Database Operations
    • SELECT Statement
    • MySQL Operators
    • DDL Statements
    • DML Statements
    • Subqueries
    • JOIN Operations
    • Aggregation
    • Case Study
    • πŸ“ Assignments
  • Graphics in Python
  • Threads in Python
    • Introduction to Threads
    • Process vs Threads
    • Concurrent Programming & GIL
    • Uses of Threads
    • Creating Threads
    • Single Tasking
    • Multi Tasking
    • Thread Synchronization
    • πŸ“ Assignments
  • Interview Questions & Answers
  • Python Case Studies
  • Multiple Choice Questions
  • πŸ“ Practice Problems
Get in Touch
  • tech2dsm@gmail.com

© Sankalan Data Tech

Python Language Interactive Tutorial

Python: Interfaces

Python Interfaces - Complete Guide

Learn how to implement interfaces in Python using ABCs and Protocols.

Created by Sankalan Data Tech Team Verified
Data Engineers, Analysts, Scientists & Trainers
Created by experienced Python developers, data engineers, and data scientists to make programming easy through practical examples, real-world experience, and clear explanations.
On this page:
  • What is an Interface?
  • Duck Typing β€” Python's Informal Interface
  • Abstract Base Classes β€” Formal Interfaces
  • Protocols β€” Modern Structural Interfaces
  • ABC vs Protocol: Which to Choose?
  • Real-World Examples
  • Best Practices
  • Try It Yourself
  • Quick Quiz
  • Frequently Asked Questions
Share this tutorial:
Twitter LinkedIn Facebook WhatsApp Reddit Telegram Email Copy Link
What You'll Learn Here
  • What is an interface β€” a contract that defines what methods a class must have
  • Duck typing β€” Python's informal approach to interfaces
  • Abstract Base Classes (ABCs) β€” formal interfaces with runtime enforcement
  • Protocols β€” modern structural interfaces for type checking
  • ABC vs Protocol β€” when to use each approach
  • Real-world use β€” practical examples you can use

What is an Interface?

An interface is like a contract. It says: "If you want to be a certain type of object, you must have these methods." It doesn't tell you how to implement them β€” it just tells you what you need to have.

Think of it like a job description. A job description says "must be able to drive" but doesn't tell you how. You could drive a car, a truck, or even a bus β€” as long as you can drive, you qualify. An interface works the same way β€” it says "must have a drive() method" but doesn't care how you implement it.

Unlike languages like Java or C# that have a special interface keyword, Python takes a different approach. It uses duck typing by default, but also provides tools like Abstract Base Classes (ABCs) and Protocols for more formal interfaces [citation:1][citation:7].

πŸ’‘ Key concept: An interface is a contract that defines what methods an object must have, not how they work. It's about "what" not "how."

Duck Typing β€” Python's Informal Interface

1

If It Walks Like a Duck...

Python follows the principle of duck typing: "If it walks like a duck and quacks like a duck, then it's a duck." In other words, Python doesn't care about the type of an object β€” it only cares about what methods it has [citation:1][citation:7].

This is Python's informal approach to interfaces. There's no formal contract β€” you just assume that an object has the methods you need. If it doesn't, Python will throw an error when you try to use it.

# Duck typing in action β€” Python's informal interface

class Dog:
    def speak(self):
        return "Woof!"
    
    def move(self):
        return "Runs on four legs"

class Cat:
    def speak(self):
        return "Meow!"
    
    def move(self):
        return "Walks silently"

class Robot:
    def speak(self):
        return "Beep boop!"
    
    def move(self):
        return "Rolls on wheels"

# This function doesn't care about the type β€” just that the object has speak()
def make_it_speak(animal):
    return animal.speak()

# All these work because all have a speak() method
print(make_it_speak(Dog()))    # Woof!
print(make_it_speak(Cat()))    # Meow!
print(make_it_speak(Robot()))  # Beep boop!

# The trade-off: no safety net
class Fish:
    def swim(self):
        return "Swimming"

# This would cause an error at runtime
# print(make_it_speak(Fish()))  # AttributeError: 'Fish' object has no attribute 'speak'

print("\nβœ… Duck typing: Python doesn't care what you are, only what you can do!")
print("❌ The trade-off: errors are only caught at runtime when you try to call a missing method.")

Duck typing key points:

  • No formal contract β€” Python doesn't enforce anything
  • Focus on behavior β€” what methods does the object have?
  • Flexible β€” any class can be used as long as it has the right methods
  • Runtime errors β€” problems are caught when you try to use the missing method
  • EAFP principle β€” Easier to Ask for Forgiveness than Permission

Quick Check: What is duck typing? (Answer: Python focuses on what an object can do, not what it is)

Abstract Base Classes β€” Formal Interfaces

2

Creating Formal Interfaces with ABCs

When you need a formal interface that's enforced at runtime, you use Abstract Base Classes (ABCs). ABCs are classes that can't be instantiated β€” they exist only to be inherited from [citation:1][citation:3][citation:9].

When a class inherits from an ABC, it must implement all abstract methods. If it doesn't, Python throws an error when you try to create an object. This is like having a bouncer at the door β€” you can't get in unless you meet all the requirements [citation:3][citation:9].

# Abstract Base Classes β€” formal interfaces

from abc import ABC, abstractmethod

# Define a formal interface
class Printable(ABC):
    """Interface: anything that can be printed must have these methods"""
    
    @abstractmethod
    def print_document(self, document):
        """Print a document β€” must be implemented"""
        pass
    
    @abstractmethod
    def get_status(self):
        """Get printer status β€” must be implemented"""
        pass

# A class that implements the interface properly
class LaserPrinter(Printable):
    def __init__(self):
        self.toner_level = 100
    
    def print_document(self, document):
        self.toner_level -= 5
        return f"Laser printing: {document} (toner: {self.toner_level}%)"
    
    def get_status(self):
        return f"Laser printer ready, toner: {self.toner_level}%"

# Another class that implements the interface
class InkjetPrinter(Printable):
    def __init__(self):
        self.ink_level = 80
    
    def print_document(self, document):
        self.ink_level -= 3
        return f"Inkjet printing: {document} (ink: {self.ink_level}%)"
    
    def get_status(self):
        return f"Inkjet printer ready, ink: {self.ink_level}%"

# This would cause an error β€” missing abstract method
class BrokenPrinter(Printable):
    def print_document(self, document):
        return f"Printing: {document}"
    # Missing get_status() β€” can't instantiate!

# Using the classes
print("=== LASER PRINTER ===")
laser = LaserPrinter()
print(laser.print_document("Report.pdf"))
print(laser.get_status())

print("\n=== INKJET PRINTER ===")
inkjet = InkjetPrinter()
print(inkjet.print_document("Photo.jpg"))
print(inkjet.get_status())

# This would cause a TypeError at instantiation:
# broken = BrokenPrinter()  # TypeError: Can't instantiate abstract class BrokenPrinter

print("\nβœ… ABCs enforce the contract at instantiation time!")
print("You can't create an object that doesn't implement all abstract methods.")

ABCs key points:

  • Formal interface β€” defines what methods must exist
  • Runtime enforcement β€” catches missing methods when you instantiate
  • Uses @abstractmethod β€” from the abc module
  • Child must implement all β€” or it remains abstract
  • Can have concrete methods β€” shared behavior for all children

Quick Check: What happens if a class inherits from an ABC but doesn't implement all abstract methods? (Answer: You can't instantiate it β€” Python raises a TypeError)

Protocols β€” Modern Structural Interfaces

3

Structural Subtyping with Protocols

Protocols are a newer way to define interfaces in Python (introduced in Python 3.8). They use structural subtyping β€” a class doesn't need to explicitly inherit from the protocol. It just needs to have the right methods with the right signatures [citation:1][citation:7][citation:8].

Protocols are great for static type checking (with tools like mypy) and for creating loosely coupled code. The implementing class doesn't even need to know about the protocol β€” it just happens to have the right methods [citation:1][citation:8].

# Protocols β€” structural interfaces

from typing import Protocol

# Define a protocol
class Flyable(Protocol):
    """Anything that can fly must have a fly() method"""
    
    def fly(self) -> str:
        """Return a string describing the flight"""
        pass

# Classes that implement the protocol (without inheriting from it!)
class Bird:
    def fly(self) -> str:
        return "Flapping wings and soaring"
    
    def sing(self) -> str:
        return "Chirping"

class Airplane:
    def fly(self) -> str:
        return "Engines roaring, taking off"
    
    def land(self) -> str:
        return "Landing gear down"

class Drone:
    def fly(self) -> str:
        return "Humming and hovering"
    
    def take_photo(self) -> str:
        return "Photo taken"

# This class does NOT implement the protocol
class Fish:
    def swim(self) -> str:
        return "Swimming in water"

# Function that accepts any Flyable (using type hints)
def send_to_sky(flyer: Flyable) -> str:
    return flyer.fly()

# All these work because they have fly()
print(send_to_sky(Bird()))      # Flapping wings and soaring
print(send_to_sky(Airplane()))  # Engines roaring, taking off
print(send_to_sky(Drone()))     # Humming and hovering

# This would fail type checking (but run if ignored)
# print(send_to_sky(Fish()))    # AttributeError: 'Fish' object has no attribute 'fly'

print("\nβœ… Protocols: The class doesn't need to know about the interface!")
print("It just needs to have the right methods.")
print("This is called 'structural subtyping.'")

Protocols key points:

  • Structural subtyping β€” classes don't need to inherit from the protocol
  • Static type checking β€” works with mypy, pyright, etc.
  • No runtime enforcement by default β€” but can use @runtime_checkable
  • Decoupled β€” the implementing class doesn't depend on the protocol
  • Modern approach β€” introduced in Python 3.8

Quick Check: What's the main difference between ABCs and Protocols? (Answer: ABCs require inheritance and enforce at runtime; Protocols use structural subtyping and are for static type checking)

ABC vs Protocol: Which to Choose?

4

Making the Right Choice

So when should you use ABCs and when should you use Protocols? The answer depends on your needs. Here's a simple way to think about it [citation:1][citation:8]:

# Decision Matrix: ABC vs Protocol

# ---------- USE ABC WHEN ----------

# 1. You need runtime enforcement
class Storage(ABC):
    @abstractmethod
    def save(self, data):
        pass
    
    @abstractmethod
    def load(self):
        pass

class FileStorage(Storage):
    def save(self, data):
        return f"Saving: {data}"
    
    def load(self):
        return "Loading data"
# βœ… Runtime check: can't create FileStorage without implementing both methods


# 2. You want to share default helper methods
class Logger(ABC):
    @abstractmethod
    def log(self, message):
        pass
    
    # Concrete method β€” shared by all children
    def log_error(self, message):
        self.log(f"ERROR: {message}")
    
    def log_info(self, message):
        self.log(f"INFO: {message}")

class ConsoleLogger(Logger):
    def log(self, message):
        print(f"Console: {message}")
# βœ… ConsoleLogger inherits log_error() and log_info() for free


# 3. You need isinstance() checks with inheritance
# βœ… ABCs support isinstance() by default


# ---------- USE PROTOCOL WHEN ----------

# 1. Your class shouldn't depend on the interface
from typing import Protocol

class Runner(Protocol):
    def run(self) -> str: ...

# Some third-party class that we can't modify
class Athlete:
    def run(self) -> str:
        return "Running fast"
# βœ… Athlete doesn't need to know about Runner protocol


# 2. You want loose coupling
# βœ… The protocol can change without modifying implementers


# 3. You're working with static type checking
def make_them_run(runner: Runner) -> str:
    return runner.run()
# βœ… mypy will check that Athlete satisfies Runner


# ---------- ABC vs Protocol Decision Table ----------

"""
| Use Case                          | Choose ABC | Choose Protocol |
|-----------------------------------|------------|-----------------|
| Need runtime enforcement          | βœ… Yes     | ❌ No (unless @runtime_checkable) |
| Want to share helper methods      | βœ… Yes     | ❌ No           |
| Class shouldn't depend on you     | ❌ No      | βœ… Yes          |
| Working with third-party classes  | ❌ No      | βœ… Yes          |
| Need isinstance() support         | βœ… Yes     | ❌ No           |
| Static type checking              | βœ… Yes     | βœ… Yes          |
| Multiple inheritance              | βœ… Yes     | βœ… Yes (no conflicts) |
| Library internal code             | βœ… Yes     | Sometimes       |
| Public API for users              | Sometimes  | βœ… Preferred    |
"""

print("βœ… Choose ABC when you need runtime enforcement and shared behavior")
print("βœ… Choose Protocol when you want loose coupling and structural typing")

ABC vs Protocol key points:

  • ABC β€” runtime enforcement, shared methods, class depends on interface
  • Protocol β€” static type checking, loose coupling, interface depends on class
  • ABC for internal code β€” when you control all implementations
  • Protocol for public APIs β€” when users should be able to plug in their own types
  • Both can be used together β€” ABCs internally, Protocols externally [citation:8]

Quick Check: When should you use a Protocol instead of an ABC? (Answer: When you want loose coupling and the class shouldn't depend on your interface)

Real-World Examples

5

Seeing Interfaces in Action

# Real-world example: A Plugin System

from abc import ABC, abstractmethod
from typing import Protocol
import json

# ---- Part 1: Using ABC for Internal Plugins ----

class Plugin(ABC):
    """Abstract base class for all plugins"""
    
    @abstractmethod
    def name(self) -> str:
        """Return the plugin's name"""
        pass
    
    @abstractmethod
    def process(self, data: dict) -> dict:
        """Process the data and return modified data"""
        pass
    
    @abstractmethod
    def validate(self, data: dict) -> bool:
        """Validate that the data can be processed"""
        pass

class LoggingPlugin(Plugin):
    def name(self) -> str:
        return "Logging Plugin"
    
    def process(self, data: dict) -> dict:
        print(f"[LOG] Processing: {data}")
        data["logged"] = True
        return data
    
    def validate(self, data: dict) -> bool:
        return isinstance(data, dict)

class EncryptionPlugin(Plugin):
    def name(self) -> str:
        return "Encryption Plugin"
    
    def process(self, data: dict) -> dict:
        data["encrypted"] = True
        data["data"] = "πŸ”’ " + str(data.get("data", ""))
        return data
    
    def validate(self, data: dict) -> bool:
        return "data" in data

# ---- Part 2: Using Protocol for External Plugins ----

class DataExporter(Protocol):
    """Protocol for data exporters (structural)"""
    
    def export(self, data: list) -> str:
        """Export data to a string format"""
        pass
    
    def get_format_name(self) -> str:
        """Return the format name"""
        pass

# These classes don't import or know about DataExporter protocol
class JSONExporter:
    def export(self, data: list) -> str:
        return json.dumps(data, indent=2)
    
    def get_format_name(self) -> str:
        return "JSON"

class CSVExporter:
    def export(self, data: list) -> str:
        if not data:
            return ""
        headers = data[0].keys()
        lines = [",".join(headers)]
        for item in data:
            lines.append(",".join(str(item.get(h, "")) for h in headers))
        return "\n".join(lines)
    
    def get_format_name(self) -> str:
        return "CSV"

# ---- Part 3: Using the System ----

class PluginManager:
    """Manages plugins (uses ABC-based plugins)"""
    
    def __init__(self):
        self.plugins = []
    
    def register(self, plugin: Plugin):
        self.plugins.append(plugin)
    
    def process_data(self, data: dict) -> dict:
        result = data.copy()
        for plugin in self.plugins:
            if plugin.validate(result):
                result = plugin.process(result)
        return result

def export_data(exporters: list, data: list):
    """Function that works with any exporter (structural)"""
    for exporter in exporters:
        print(f"--- {exporter.get_format_name()} ---")
        print(exporter.export(data))
        print()

# ---- Demo ----

print("=" * 50)
print("PLUGIN SYSTEM WITH INTERFACES")
print("=" * 50)

# Using ABC-based plugins
manager = PluginManager()
manager.register(LoggingPlugin())
manager.register(EncryptionPlugin())

print("\n1. PROCESSING WITH PLUGINS (ABC)")
data = {"user": "Alice", "data": "Hello World"}
print(f"Original data: {data}")
processed = manager.process_data(data)
print(f"Processed data: {processed}")

# Using Protocol-based exporters
print("\n2. EXPORTING DATA (PROTOCOL)")
sample_data = [
    {"name": "Alice", "age": 30},
    {"name": "Bob", "age": 25}
]

exporters = [JSONExporter(), CSVExporter()]
export_data(exporters, sample_data)

print("\nβœ… ABCs for internal code with runtime enforcement")
print("βœ… Protocols for public API with loose coupling")
print("Both approaches work together in the same system!")

Real-world example key points:

  • Plugin (ABC) β€” enforces that all plugins have name(), process(), validate()
  • LoggingPlugin, EncryptionPlugin β€” implement the ABC interface
  • DataExporter (Protocol) β€” defines export interface without requiring inheritance
  • JSONExporter, CSVExporter β€” don't know about the protocol, just have the right methods
  • Both approaches β€” work together in the same system

Quick Check: In the example, what's the advantage of using Protocol for exporters? (Answer: Exporters don't need to import or depend on the interface)

Best Practices for Interfaces

6

Using Interfaces Effectively

# Best practices for interfaces

from abc import ABC, abstractmethod
from typing import Protocol

# 1. Name interfaces clearly
#  Good β€” descriptive names
class Database(ABC):
    @abstractmethod
    def connect(self):
        pass

class FileReader(Protocol):
    def read(self) -> str: ...

#  Bad β€” vague names
class D(ABC):
    pass

class FR(Protocol):
    pass

# 2. Keep interfaces focused
#  Good β€” single responsibility
class Logger(ABC):
    @abstractmethod
    def log(self, message):
        pass

class Formatter(ABC):
    @abstractmethod
    def format(self, data):
        pass

#  Bad β€” too many responsibilities
class Utility(ABC):
    @abstractmethod
    def log(self, message):
        pass
    @abstractmethod
    def format(self, data):
        pass
    @abstractmethod
    def save(self, data):
        pass

# 3. Use docstrings to document interfaces
class Payment(ABC):
    @abstractmethod
    def process(self, amount: float) -> str:
        """
        Process a payment of the given amount.
        
        Args:
            amount: The amount to process
            
        Returns:
            str: Status message
        """
        pass

# 4. For Protocols, keep them simple
class Runner(Protocol):
    def run(self) -> str:
        """A simple protocol with one method"""
        ...

# 5. Use ABCs when you need to share code
class Writer(ABC):
    @abstractmethod
    def write(self, content):
        pass
    
    # Shared helper
    def write_line(self, content):
        return self.write(content + "\n")

# 6. Use Protocols for structural typing
class Processor(Protocol):
    def process(self, data: dict) -> dict:
        ...

# 7. Combine both approaches
# Use ABCs internally, Protocols externally
class InternalPlugin(ABC):
    """Internal code β€” uses ABC"""
    @abstractmethod
    def execute(self):
        pass

class PublicPlugin(Protocol):
    """Public API β€” uses Protocol"""
    def execute(self) -> None: ...

# 8. Don't overcomplicate
# Simple duck typing is often enough for small projects
def print_message(obj):
    """Just call the method β€” duck typing works fine"""
    return obj.message()

Best practices summary:

  • Clear names β€” make it obvious it's an interface
  • Keep it focused β€” each interface should have one purpose
  • Document β€” explain what the interface requires
  • ABC for code sharing β€” when you need default implementations
  • Protocol for loose coupling β€” when classes shouldn't depend on your interface
  • Combine approaches β€” ABCs internally, Protocols externally
  • Don't overcomplicate β€” duck typing is fine for simple cases

Quick Check: What's a good reason to use Protocols over ABCs? (Answer: When you want loose coupling and the implementing class shouldn't depend on your interface)

Try It Yourself

Experiment with interfaces in the editor below.

Loading Pyodide... 0%
Python Code Editor
========================================
INTERFACES PRACTICE
========================================

1. DEFINING AN ABC INTERFACE

2. IMPLEMENTING THE ABC

3. DEFINING A PROTOCOL

4. SATISFYING THE PROTOCOL

5. USING THE CLASSES
=== MEDIA PLAYERS (ABC) ===
🎡 Playing music
⏸️ Music paused
Volume: 50%
🎬 Playing video
⏹️ Video stopped

=== RENDERERS (PROTOCOL) ===
Rendering: πŸ“„ Rendering PDF
Rendering: 🌐 Rendering HTML
Rendering: πŸ–ΌοΈ Rendering Image

Interfaces practice complete!
πŸ†

You've Got It!

You now understand interfaces in Python. You know how to use duck typing, create formal interfaces with ABCs, and use Protocols for structural typing.

Quick Quiz

Test what you've learned:

1. What is an interface in Python?
2. What is duck typing in Python?
3. Which module is used to create Abstract Base Classes?
4. What's the main advantage of Protocols over ABCs?
5. When should you use an ABC instead of a Protocol?

Frequently Asked Questions

Does Python have an interface keyword like Java? β–Ό

No, Python doesn't have a special interface keyword like Java or C#. Instead, Python uses duck typing by default, and provides Abstract Base Classes (ABCs) and Protocols for more formal interface-like behavior [citation:1][citation:7].

Can I use isinstance() with Protocols? β–Ό

By default, Protocols don't work with isinstance(). You need to use the @runtime_checkable decorator to enable this. However, even then, runtime-checkable protocols only check that methods exist β€” not that they have the correct signatures [citation:1][citation:8].

What's the difference between an abstract class and an interface? β–Ό

In Python, the distinction is less strict than in other languages. An abstract class can have both abstract and concrete methods, and it can maintain state. An interface typically only defines method signatures (no implementation, no state). In Python, ABCs are used for both [citation:9][citation:8].

What's a common interview question about interfaces? β–Ό

Common questions include: "What is duck typing?" "How do you create an interface in Python?" "What's the difference between an ABC and a Protocol?" "When would you use an ABC instead of duck typing?" and "What is the abc module used for?"

Should I use ABCs or Protocols in my code? β–Ό

It depends on your needs [citation:8]. Use ABCs when you need runtime enforcement and want to share helper methods. Use Protocols when you want loose coupling and your classes shouldn't depend on your interface. Many projects use both β€” ABCs internally and Protocols for public APIs.

What are the built-in ABCs in Python? β–Ό

Python's collections.abc module provides many useful ABCs including: Container, Iterable, Sequence, MutableSequence, Set, MutableSet, Mapping, MutableMapping, and more [citation:2][citation:5]. These let you check if a class implements a particular interface.

Where to Go From Here

Now that you understand interfaces in Python, check out these related topics:

Abstract Class vs Interface

Learn the key differences between these two concepts.

Learn More β†’

Abstract Methods

Learn more about methods that must be implemented.

Learn More β†’

Polymorphism

Learn how interfaces enable polymorphic behavior.

Learn More β†’
Interview Resources
  • Python Syntax & Variables Interview Questions
  • Top SQL Interview Questions & Answers
  • SQL Joins: Displaying Data from Multiple Tables FAQ
  • Python Lists and Dictionaries Interview Questions
  • Python OOP Interview Questions
  • SQL Set Operators Interview Questions
Previous: Abstract Method Next: Abstract Class vs Interface β†’