Skip to main content

Protocols

A protocol is a contract that any type can satisfy by defining the right methods. The runtime dispatches through the protocol rather than checking concrete types, which is what makes the duck-typing model work.

Source-of-record: Objects/abstract.c, Lib/typing.py, Lib/collections/abc.py.

Iterator protocol

MethodSignatureRole
__iter__(self) -> IteratorReturn an iterator. Containers return a new iterator each call.
__next__(self) -> AnyAdvance. Raise StopIteration to end.

iter(obj) returns:

  1. The result of obj.__iter__() if defined.
  2. Otherwise an iterator that calls obj.__getitem__(0), (1), ... until IndexError (legacy).

iter(callable, sentinel) returns an iterator that calls callable() until it returns sentinel.

Async-iterator protocol

MethodSignatureRole
__aiter__(self) -> AsyncIteratorReturn async iterator.
__anext__(self) -> Awaitable[Any]Awaitable yielding next value or raising StopAsyncIteration.

async for x in obj: calls __aiter__ once, then awaits __anext__ each iteration.

Awaitable protocol

MethodReturns
__await__An iterator. yield from this iterator suspends the awaiting frame.

Native coroutines (async def) implement __await__ implicitly via the coroutine state machine. Generator-based coroutines mark themselves with @types.coroutine.

Sequence protocol

MethodRole
__getitem__(self, i)Element access (int or slice).
__setitem__(self, i, v)Element assignment (mutable).
__delitem__(self, i)Element delete (mutable).
__len__(self)Length.
__contains__(self, x)Containment (optional; falls back to iteration).
__iter__Optional; required only if iteration order differs from __getitem__.
__reversed__Optional reverse iteration.
__concat__ / __iconcat__Concatenation (operator forms via __add__).
__repeat__ / __irepeat__Repetition (operator forms via __mul__).

collections.abc.Sequence is the ABC, layering convenience methods on the core protocol.

Mapping protocol

MethodRole
__getitem__(self, k)Value lookup.
__setitem__(self, k, v)Assignment.
__delitem__(self, k)Delete.
__len__(self)Number of keys.
__iter__(self)Iterate keys.
__contains__(self, k)Key membership.
keys(), values(), items()Convenience accessors.
get(k, default)Defaulting lookup.
__missing__(self, k)dict.__getitem__ fallback.
__or__ / __ror__ / __ior__PEP 584 dict union.

Number protocol

The C-level number protocol exposes per-operator slots. Python-side analogues are the dunder methods (see Special methods). The key C-API entry points:

C functionPython equivalent
PyNumber_Add(a, b)a + b
PyNumber_InPlaceAdd(a, b)a += b
PyNumber_Index(a)operator.index(a)
PyNumber_Float(a)float(a)
PyNumber_Long(a)int(a)
PyNumber_TrueDivide(a, b)a / b
PyNumber_FloorDivide(a, b)a // b
PyNumber_MatrixMultiply(a, b)a @ b
PyNumber_Power(a, b, mod)pow(a, b, mod)

Buffer protocol (PEP 3118)

Provides zero-copy access to underlying memory. Implementing types:

C slotPython dunderRole
bf_getbuffer__buffer__(self, flags)Acquire view.
bf_releasebuffer__release_buffer__(self, view)Release view.

The view struct (Py_buffer) carries buf, obj, len, readonly, itemsize, format, ndim, shape, strides, suboffsets, internal.

memoryview is the Python-level wrapper over a Py_buffer.

Descriptor protocol

MethodRole
__get__(self, obj, objtype=None)Attribute read.
__set__(self, obj, value)Attribute write (makes a data descriptor).
__delete__(self, obj)Attribute delete (makes a data descriptor).
__set_name__(self, owner, name)Called during class creation.

Data descriptors take precedence over instance __dict__. Non-data descriptors (only __get__) do not.

Context manager protocol

Synchronous

MethodRole
__enter__(self)Setup. Return value bound by as.
__exit__(self, exc_type, exc_value, traceback)Teardown. Returns truthy to suppress.

Asynchronous

MethodRole
__aenter__(self) -> AwaitableAwaitable setup.
__aexit__(self, exc_type, exc_value, tb) -> AwaitableAwaitable teardown.

Hash protocol

hash(x) invokes type(x).__hash__(x). The result is an int that fits in Py_hash_t (signed pointer-width).

Rule
x == y implies hash(x) == hash(y). Violations are bugs.
If __eq__ is overridden and __hash__ is not, __hash__ is set to None.
hash(-1) is normalised to -2 (internal sentinel value).
The PEP 456 SipHash is used for str, bytes, memoryview.

Comparison protocol

__eq__, __lt__, __le__, __gt__, __ge__, __ne__. Reflected: the runtime tries the right operand's reflected method if the left returns NotImplemented. See Expressions -> Comparisons.

Call protocol

SlotRole
tp_callobj(*args, **kwargs).
tp_vectorcallFast path: (*args, nargsf, kwnames) packed.
tp_vectorcall_offsetOffset into the object where the vectorcall function lives.

Vectorcall (PEP 590)

A type with Py_TPFLAGS_HAVE_VECTORCALL set advertises an optimised calling convention:

PyObject* vectorcallfunc(PyObject *callable,
PyObject *const *args,
size_t nargsf,
PyObject *kwnames);
FieldMeaning
callableThe callable itself.
argsPointer to the argument array.
nargsf`nargs
kwnamesTuple of keyword names for trailing args, or NULL.

Many built-in callables (builtin_function_or_method, bound methods, classes) implement vectorcall for low-overhead calls.

Generic protocol (PEP 585, 604, 695)

HookRole
__class_getitem__(cls, item)cls[item] syntax (e.g. list[int]).
__mro_entries__(self, bases)Replace a generic alias in __bases__.
__type_params__Tuple of TypeVar/TypeVarTuple/ParamSpec.
__typing_subst__Used by Generic during substitution.

Path-like protocol

MethodReturns
__fspath__(self)str or bytes representing a filesystem path.

os.fspath(x) is the public entry point; it accepts str, bytes, or an object with __fspath__.

Pickle protocol

Pickling consults, in order:

  1. The dispatch of the configured Pickler.
  2. __reduce_ex__(protocol).
  3. __reduce__().
  4. copyreg.__reduce_ex__ defaults.

Hooks for state:

MethodRole
__getstate__()Return state to pickle.
__setstate__(state)Restore from state.
__getnewargs_ex__()(args, kwargs) for __new__.
__getnewargs__()args for __new__.

Copy protocol

copy.copy(x) consults __copy__. copy.deepcopy(x, memo) consults __deepcopy__. If neither is defined, it falls back to the pickle protocol.

Format protocol

format(x, spec) calls x.__format__(spec). The format spec mini-language is described in Expressions -> f-string interpolation and the format spec mini-language docs.

with and async with re-entrancy

Re-entering the same context manager on multiple with statements is allowed if the manager supports it. The default contextlib.contextmanager decorator does not; use contextlib.contextmanager(... ) carefully or build a re-entrant manager from scratch.

Gopy status

Every protocol listed is implemented. Built-in types pass the ABC isinstance checks (isinstance({}, Mapping), etc.) via the same __subclasshook__ plumbing CPython uses.

Reference

  • Objects/abstract.c. The protocol entry points.
  • Lib/collections/abc.py. The ABC tier on top of the protocols.
  • Special methods.
  • Data model.