UPDATE: this function will now traverse an object's subclass chain and extract ALL abstractmethods. To use the old behavior, set nested=False
.
By convention, protocols are groups of special methods that describe common behaviors. You can roughly infer protocols from the abstract methods of the collections.abc
module (Python 3.3+); see also the docs. Automate this listing with the following:
Given
import abc
import collections as ct
Code
def get_protocols(source=ct.abc, nested=True):
"""Return a dict of protocols from source abstractmethods only."""
dd = ct.defaultdict(set)
for objname in dir(source):
if objname.startswith("_"):
continue
obj = getattr(source, objname)
classes = obj.__mro__ if nested else [obj]
for cls in classes:
if cls is object:
continue
abmethods = sorted(cls.__abstractmethods__)
if not abmethods:
continue
dd[objname] |= set(abmethods)
return dict(dd)
Demo
get_protocols()
Output
{
'AsyncGenerator': {'__aiter__', '__anext__', 'asend', 'athrow'},
'AsyncIterable': {'__aiter__'},
'AsyncIterator': {'__aiter__', '__anext__'},
'Awaitable': {'__await__'},
'ByteString': {'__contains__', '__getitem__', '__iter__', '__len__', '__reversed__'},
'Callable': {'__call__'},
'Collection': {'__contains__', '__iter__', '__len__'},
'Container': {'__contains__'},
'Coroutine': {'__await__', 'send', 'throw'},
'Generator': {'__iter__', '__next__', 'send', 'throw'},
'Hashable': {'__hash__'},
'ItemsView': {'__contains__', '__iter__', '__len__'},
'Iterable': {'__iter__'},
'Iterator': {'__iter__', '__next__'},
'KeysView': {'__contains__', '__iter__', '__len__'},
'Mapping': {'__contains__', '__getitem__', '__iter__', '__len__'},
'MappingView': {'__len__'},
'MutableMapping': {'__contains__', '__delitem__', '__getitem__', '__iter__', '__len__', '__setitem__'},
'MutableSequence': {'__contains__', '__delitem__', '__getitem__', '__iter__', '__len__', '__reversed__', '__setitem__', 'insert'},
'MutableSet': {'__contains__', '__iter__', '__len__', 'add', 'discard'},
'Reversible': {'__iter__', '__reversed__'},
'Sequence': {'__contains__', '__getitem__', '__iter__', '__len__', '__reversed__'},
'Set': {'__contains__', '__iter__', '__len__'},
'Sized': {'__len__'},
'ValuesView': {'__contains__', '__iter__', '__len__'}
}
NOTE: When sub-classing, these are (required) abstract methods that do not include the mixin methods. Example: sub-classing collections.abc.Mappings
will provide methods .keys()
, .values()
, .items()
(no listed) once the protocol is implemented.
NOTE: Only abstractmethods are listed. Some methods are excluded, e.g. close()
on all generator-like functions.