← Back to Python

All Topics

Advertisement

Learn/Python/Python Advanced

Protocol Types - Structural Subtyping

Topic: Type System

Advertisement

Introduction

Protocol classes from typing define interfaces for structural subtyping. Unlike nominal subtyping, protocols check interface compatibility at runtime.

Basic Protocol

from typing import Protocol

class Drawable(Protocol):
    def draw(self) -> None:
        ...

class Circle:
    def draw(self) -> None:
        print("Drawing circle")

class Square:
    def draw(self) -> None:
        print("Drawing square")

def render(item: Drawable):
    item.draw()

render(Circle())
render(Square())

Protocol with Type Checking

from typing import Protocol, runtime_checkable

@runtime_checkable
class Comparable(Protocol):
    def __lt__(self, other: "Comparable") -> bool:
        ...

class Integer:
    def __init__(self, value: int):
        self.value = value
    
    def __lt__(self, other: "Integer") -> bool:
        return self.value < other.value

a = Integer(1)
b = Integer(2)
print(a < b)  # True
isinstance(a, Comparable)  # True

Protocol Inheritance

from typing import Protocol

class Printable(Protocol):
    def print(self) -> None:
        ...

class Serializable(Protocol):
    def to_json(self) -> str:
        ...

class Document(Printable, Serializable):
    def print(self) -> None:
        pass
    
    def to_json(self) -> str:
        return "{}"

Generic Protocols

from typing import TypeVar, Generic, Protocol

T = TypeVar("T")

class Container(Protocol[T]):
    def get(self) -> T:
        ...

class Box(Generic[T]):
    def __init__(self, item: T):
        self._item = item
    
    def get(self) -> T:
        return self._item

box: Box[int] = Box(42)
container: Container[int] = box

Protocol for Duck Typing

from typing import Iterator, Iterable

def sum_all(numbers: Iterable[int]) -> int:
    return sum(numbers)

class NumberGenerator:
    def __iter__(self):
        return iter([1, 2, 3])

result = sum_all(NumberGenerator())  # Works with any iterable

Practice Problems

  1. Create a protocol for file-like objects
  2. Implement generic protocol with bounds
  3. Use runtime_checkable protocol
  4. Define protocol for database operations
  5. Create protocol composition

Advertisement

Advertisement

Need More Practice?

Get personalized Python help from ChatWhole's AI-powered platform.

Get Expert Help →