AI Skill Report Card

Choosing Abstract Base Classes

A88·Aug 22, 2026·Source: Web
14 / 15
Python
from collections.abc import Mapping, Sequence, Iterable # Duck-typing check: does obj behave like a mapping? if isinstance(obj, Mapping): for key in obj: print(key, obj[key]) # Custom container: implement minimum methods, get the rest free class FrozenDict(Mapping): def __init__(self, data): self._data = dict(data) def __getitem__(self, key): return self._data[key] def __iter__(self): return iter(self._data) def __len__(self): return len(self._data) # __contains__, keys, items, values, get, __eq__, __ne__ come for free
Recommendation
Add an example showing a 'bad outcome' explicitly (e.g., someone incorrectly reimplementing Mapping methods) to reinforce contrast, not just correct usage.
14 / 15

Progress:

  • Step 1: Identify what behavior is needed (iteration? indexing? mutation? hashing?)
  • Step 2: Pick the narrowest ABC that matches (don't over-implement)
  • Step 3: Check the ABC's "Abstract Methods" — implement only those
  • Step 4: Check "Mixin Methods" — these come free from the abstract ones
  • Step 5: Use isinstance()/issubclass() for duck-typing checks instead of concrete types
  • Step 6: Register unrelated classes with .register() if virtual subclassing is needed

Reference table (most-used ABCs)

ABCAbstract MethodsInherits FromUse for
Iterable__iter__anything you can loop over
Iterator__next__Iterablestateful iteration objects
Container__contains__in operator support
Sized__len__len() support
Hashable__hash__usable as dict key / set member
Collection__contains__, __iter__, __len__Sized, Iterable, Containergeneral-purpose container check
Sequence__getitem__, __len__Reversible, Collectionordered, indexable (list-like)
MutableSequence+ __setitem__, __delitem__, insertSequencemutable list-like
Mapping__getitem__, __iter__, __len__Collectiondict-like read access
MutableMapping+ __setitem__, __delitem__Mappingdict-like read/write
Set__contains__, __iter__, __len__Collectionset-like, supports &, |, -, ^
MutableSet+ add, discardSetmutable set-like
Callable__call__function-like objects
Recommendation
Include a brief note on typing.Protocol vs collections.abc for structural typing scenarios, since users often conflate the two.
17 / 20

Example 1: Input: "I need a class that supports len(), in, and iteration, but I don't need indexing or mutation." Output: Inherit from Collection and implement __contains__, __iter__, __len__. Don't reach for Sequence — it forces __getitem__ and implies order/indexing you don't need.

Example 2: Input: "How do I check if a function argument is 'list-like' without requiring it to actually be a list?" Output:

Python
from collections.abc import Sequence def process(items): if not isinstance(items, Sequence): raise TypeError("items must be a Sequence") return items[0], len(items)

This accepts tuple, custom Sequence subclasses, etc., while rejecting str only if that's explicitly desired (note str is a Sequence — guard separately if needed).

Example 3: Input: "Building a custom read-only set-like collection backed by a database query." Output: Inherit from Set, implement __contains__, __iter__, __len__. Get __le__, __lt__, __gt__, __ge__, __eq__, __and__, __or__, __sub__, __xor__, isdisjoint for free.

Recommendation
The reference table is excellent but could add a short blurb on Reversible and Awaitable ABCs for completeness given async code prevalence.
  • Implement the minimum abstract set; let mixins provide the rest. Overriding a mixin method is fine if you have a faster implementation (e.g., custom __contains__ for O(1) lookup backed by a hash index).
  • Prefer ABC checks over concrete type checks (isinstance(x, Mapping) over isinstance(x, dict)) to support duck-typing and third-party implementations.
  • Use Iterable/Iterator distinction correctly: an Iterable produces an Iterator via __iter__; don't conflate the two when type-checking.
  • Register virtual subclasses when a class already satisfies the interface but can't/shouldn't inherit: Sequence.register(MyExternalType).
  • Remember str, bytes, range are Sequence — guard against accidentally treating strings as sequences of characters when you meant "list-like".
  • For generic type hints, prefer collections.abc classes over typing equivalents (e.g., collections.abc.Sequence[int]) — typing aliases are deprecated in favor of these.
  • Don't implement Mapping/Sequence from scratch — subclass the ABC and only fill abstract methods; reimplementing keys(), items(), get(), etc. manually is redundant and error-prone.
  • Don't use Sequence when you just need Iterable — forcing __getitem__/__len__ unnecessarily overconstrains simple generators/streams.
  • Don't forget Hashable immutability contract — if you implement __hash__, ensure the object's hash-relevant state never changes after creation.
  • Don't check isinstance(x, list) for "list-like" duck typing — this excludes valid alternative implementations; use MutableSequence or Sequence.
  • Don't assume Set mixins imply sorted orderSet operations don't guarantee ordering; that's a Sequence concern.
0
Grade AAI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
14/15
Workflow
14/15
Examples
17/20
Completeness
18/20
Format
15/15
Conciseness
14/15