pythonadvanced
Protocol Classes for Structural Typing
Define interfaces with Protocol for duck-typing that works with static type checkers.
pythonPress ⌘/Ctrl + Shift + C to copy
from typing import Protocol, runtime_checkable
from dataclasses import dataclass
@runtime_checkable
class Drawable(Protocol):
x: float
y: float
def draw(self) -> str: ...
def area(self) -> float: ...
@dataclass
class Circle:
x: float
y: float
radius: float
def draw(self) -> str:
return f"Circle at ({self.x}, {self.y}) r={self.radius}"
def area(self) -> float:
import math
return math.pi * self.radius ** 2
@dataclass
class Square:
x: float
y: float
side: float
def draw(self) -> str:
return f"Square at ({self.x}, {self.y}) s={self.side}"
def area(self) -> float:
return self.side ** 2
def render(shapes: list[Drawable]) -> None:
for shape in shapes:
print(f"{shape.draw()} area: {shape.area():.2f}")
c = Circle(0, 0, 5)
print(isinstance(c, Drawable)) # True
render([Circle(0, 0, 5), Square(1, 1, 3)])Use Cases
- dependency injection
- plugin systems
- testable interfaces
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
pythonbeginner
Dataclass with Validation
Python dataclass with __post_init__ field validation, type coercion, and descriptive error messages.
Best for: Data transfer objects
#dataclass#validation
pythonintermediate
Python Dataclass Advanced Patterns
Advanced dataclass usage with validation, post-init processing, slots, and frozen instances.
Best for: Type-safe data models without ORMs
#python#dataclass
pythonadvanced
Python Advanced Typing Patterns
Advanced type hints with Protocol, TypeVar, Generic, overload, and TypeGuard for safer code.
Best for: Building type-safe generic containers
#python#typing
pythonintermediate
Implement the Iterator Protocol
Create custom iterators using __iter__ and __next__ for lazy evaluation.
Best for: Batch processing
#python#iterator