Standard inheritance checks in Python are highly optimized C-level operations. If you check isinstance(obj, MyClass), CPython simply traverses the __mro__ (Method Resolution Order) tuple of obj.__class__.
However, checking isinstance(obj, abc.Sized) is significantly heavier.
Because collections.abc.Sized is an Abstract Base Class powered by the ABCMeta metaclass, it overrides the default __instancecheck__ and __subclasscheck__ mechanisms.
When you evaluate isinstance(obj, abc.Sized), the ABCMeta metaclass intercepts the check and looks for a special class method called __subclasshook__ on Sized.
The Sized ABC implements it roughly like this:
class Sized(metaclass=ABCMeta):
@classmethod
def __subclasshook__(cls, C):
if cls is Sized:
if any("__len__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented- Python calls
Sized.__instancecheck__(obj). - This triggers
Sized.__subclasshook__(obj.__class__). - The hook dynamically iterates through the entire
__mro__of the target class. - It checks the
__dict__of every class in the MRO to see if the string"__len__"exists. - If found, it returns
True, and theisinstancecheck passes—even if the object did not inherit fromSized.
The __subclasshook__ is what enables "Goose Typing." It allows standard isinstance() checks to dynamically verify structure (duck typing) instead of just checking rigid inheritance trees (nominal typing).
However, because this involves multiple Python-level function calls, MRO traversals, and dictionary lookups, isinstance against an ABC is ~4x slower than a simple hasattr check. Use it at architectural boundaries where safety is more important than microsecond performance.