A typing Protocol describes operations a static type checker expects an object to provide without requiring inheritance from that protocol.
Python Protocol: structural intent without runtime validation
Operation contract
The receipt renderer accepts a store with an amount method. The in-memory store supplies that method structurally. The function still checks the returned amount because a type annotation is not a runtime wire validator. A third-party implementation could return an invalid value despite its advertised annotation, or raise an I/O failure that the caller must handle.
Failure and ownership boundary
The fixture runs without a static checker. It proves the runtime behavior of one implementation, not that every implementation passes a type checker. runtime_checkable protocols also cannot validate full argument/result semantics merely by checking attribute presence. Python type hints: annotations do not enforce runtime arguments and Python JSON validation: reject duplicate members and non-integer amounts solve separate problems.
Working program
from typing import Protocol
class ReceiptStore(Protocol):
def amount(self, receipt_id: int) -> int: ...
class MemoryReceipts:
def amount(self, receipt_id: int) -> int:
return {41: 125}[receipt_id]
def render_amount(store: ReceiptStore, receipt_id: int) -> str:
amount = store.amount(receipt_id)
if type(amount) is not int or amount < 0:
raise ValueError("invalid minor-unit amount")
return f"R{receipt_id}:{amount}"
print(render_amount(MemoryReceipts(), 41))Output
R41:125Costs and limits
An annotation adds no database lookup optimization. The fixture performs one dictionary lookup with expected bounded hash work; a remote store would add its own latency and failure budget.
Common Mistakes
- A Protocol annotation does not validate an external implementation at runtime.
- Specify whether missing IDs raise, return None or produce a domain result.
Connected lessons
Python type hints: annotations do not enforce runtime arguments, Python classes: keep instance state separate from class state, Python JSON validation: reject duplicate members and non-integer amounts.
