Protocol Classes (PEP 544) & Structural Subtyping
1Concept
`typing.Protocol` enables static duck typing (structural subtyping). A class satisfies a Protocol if it implements the required methods and attributes, without needing to explicitly inherit from the Protocol class.
2Architecture Diagram
Protocol: class Renderable(Protocol): def render() -> str Any class with def render() satisfies Renderable automatically (Zero inheritance needed!)
3Code Example
Python 3.12
from typing import Protocol
class Renderable(Protocol):
def render(self) -> str: ...
class HtmlCard:
def render(self) -> str:
return "<div class='card'>Card Content</div>"
class JsonCard:
def render(self) -> str:
return '{"type": "card", "content": "Card Content"}'
def display_ui(component: Renderable) -> None:
print(f"Rendered: {component.render()}")
display_ui(HtmlCard())
display_ui(JsonCard())4Expected Output
Rendered: <div class='card'>Card Content</div>
Rendered: {"type": "card", "content": "Card Content"}5Key Takeaways
- ✓Decorate with `@typing.runtime_checkable` to allow `isinstance(obj, Protocol)` at runtime.
- ✓Achieves clean interface-based decoupling without rigid class inheritance trees.
- ✓Python's answer to Go interfaces and TypeScript structural typing.