Protocols & ABCs

A track of P28 · Objects & Data Modelling.

Structural versus nominal typing: protocols, ABCs and when each is the right contract for an interface.

Your function needs "anything that can .read()" — a file, a socket, a StringIO, the five-line stub your test suite fakes it with. Must every one of those inherit from your base class, or is walking like a duck enough? Python's honest answer is that both regimes exist, both are first-class, and choosing between them is a genuine design decision — not a style preference. This track is about making that choice deliberately, with the type checker on your side either way.

The structural regime is typing.Protocol: conformance by shape. Any object with the right methods satisfies the contract — no inheritance, no registration, no cooperation from the class's author — which is exactly what you need when the conforming types belong to a third-party library or to code you cannot touch. The nominal regime is abc.ABC: conformance by declared lineage, enforced at instantiation and testable with isinstance, which is exactly what you want when you own the hierarchy and intend to share real implementation between its members. The first module builds both around the same duck and makes the trade-offs concrete; the tools return in P31 (Typing & Robust Code), where they meet mypy at full strength.

The closing module extends contracts from behaviour to values. An enum replaces a scatter of magic strings with a small, closed set of named members — impossible to mistype, exhaustively checkable. A validated model applies "parse, don't just store": data is checked and normalised once, at the boundary, so the rest of the program only ever sees valid values — the idea behind libraries like pydantic, built here by hand so you know what they do. Data Modelling built objects whose states are legal; this track finishes the pillar by writing down, in checkable form, what legal means.

Contractwhat counts as conformingProtocolsstructural: shape is enoughABCsnominal: declared, isinstance-checkableEnumsclosed sets, no stringsValidateparse once, at boundary
From the question - who conforms? - to two answers, then contracts on values themselves.