All Courses
Object-Oriented Programming

Python Interfaces

What is an Interface?

An interface is like an abstract class, except it contains only abstract methods — no implementation whatsoever. Every method simply raises NotImplementedError.

Its sole purpose is to define a contract: any class that implements the interface must implement all of its methods.

⚠️ Python has no interface keyword. Like abstract classes and private attributes, interfaces in Python are a convention, not an enforced language feature. We fake them using a class where every method raises NotImplementedError.


Interface vs Abstract Class

Interface Abstract Class
Contains implemented methods? ❌ Never ✅ Yes (some methods have logic)
Contains abstract methods? ✅ All methods are abstract ✅ Some methods are abstract
Purpose Define a contract / type Provide shared logic + define a contract

How to spot an interface: if every single method raises NotImplementedError with no other logic, it's an interface.


Defining an Interface in Python

class RunCodeInterface:

    def compile_code(self):
        raise NotImplementedError("You must implement compile_code")

    def execute_code(self):
        raise NotImplementedError("You must implement execute_code")

As soon as any method has actual logic (e.g. a print statement), it is no longer a pure interface.


Naming Convention

Suffix the class name with Interface to make its role clear:

class RunCodeInterface:   # signals: this is an interface, do not instantiate

Implementing an Interface

In Python, "implementing" an interface means inheriting from it and overriding every method:

class GoCode(RunCodeInterface):
    def compile_code(self):
        print("Compile go code")

    def execute_code(self):
        print("Execute go code")


class JavaCode(RunCodeInterface):
    def compile_code(self):
        print("Compile Java code")

    def execute_code(self):
        print("Execute Java code")

Both classes implement all interface methods — they satisfy the contract. Extra methods (e.g. test()) can be added freely; the only rule is that the interface methods must be present.


Using Interfaces as a Type Hint

In Python, you can hint (but not enforce) what type a function parameter should be using a colon:

def run_code(code: RunCodeInterface):
    code.compile_code()
    code.execute_code()
  • This tells other developers: "pass something that implements RunCodeInterface"
  • Python does not enforce this — you can still pass anything
  • In strongly typed languages like Java, passing the wrong type would cause a compile-time error
go   = GoCode()
java = JavaCode()

run_code(go)    # Compile go code / Execute go code  ✅
run_code(java)  # Compile Java code / Execute Java code  ✅

What You Can and Can't Use Inside a Function

Inside run_code, you should only use methods defined in the interface:

def run_code(code: RunCodeInterface):
    code.compile_code()   # ✅ guaranteed to exist
    code.execute_code()   # ✅ guaranteed to exist
    code.test()           # ⚠️ works for JavaCode but crashes for GoCode — bad practice

The whole point of the interface type hint is that any object passed in is guaranteed to have those methods. Using methods outside the interface breaks that guarantee.


Python vs Strongly Typed Languages (e.g. Java)

Behaviour Python Java
Interface keyword ❌ (use a class by convention) interface keyword
Enforce implementation ❌ Raises error only at runtime ✅ Compile-time error
Type checking on parameters ❌ Hints only, not enforced ✅ Enforced at compile time
Using non-interface methods inside a function ⚠️ Works via duck typing (until it crashes) ❌ Not allowed

If an Interface Method Isn't Implemented

class BrokenCode(RunCodeInterface):
    pass   # forgot to implement compile_code and execute_code

run_code(BrokenCode())
# 💥 NotImplementedError: You must implement compile_code

Python only catches this at runtime (when the method is actually called), not before.


Key Takeaways & Recap

Concept Summary
Interface A class where every method raises NotImplementedError — no logic at all
Purpose Define a contract; act as a type for parameters
In Python Implemented via inheritance (no implements keyword)
Naming Suffix with Interface (e.g. RunCodeInterface)
Type hints param: InterfaceName — hints but doesn't enforce the type
Most useful in Strongly typed languages (Java, C#); less critical in Python due to duck typing
When you see NotImplementedError The method is abstract and must be overridden