Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Leer __subclasshook__ and Custom Membership | ABCs in Depth
Python Abstract Base Classes

__subclasshook__ and Custom Membership

Veeg om het menu te tonen

register() requires explicit opt-in for each class. __subclasshook__ goes further – it lets an ABC automatically accept any class that satisfies a structural condition, without requiring registration at all. This is how Python's built-in ABCs like Iterable work.

How __subclasshook__ Works

__subclasshook__ is a class method called by isinstance() and issubclass() before consulting the MRO or the registered subclasses. It returns:

  • True – the class is considered a subclass;
  • False – the class is explicitly not a subclass;
  • NotImplemented – fall through to normal lookup.
1234567891011121314151617181920212223
from abc import ABC, abstractmethod # ABC that automatically accepts any class with a serialize() method class Serializable(ABC): @abstractmethod def serialize(self): pass @classmethod def __subclasshook__(cls, subclass): if cls is Serializable: if any("serialize" in klass.__dict__ for klass in subclass.__mro__): return True return NotImplemented # A class that never heard of Serializable class TransactionRecord: def serialize(self): return {"id": "TX-001", "amount": 4500.0} # Passes isinstance() without register() or inheritance print(isinstance(TransactionRecord(), Serializable)) # True print(issubclass(TransactionRecord, Serializable)) # True

How the Standard Library Uses __subclasshook__

collections.abc.Iterable uses exactly this mechanism – any class that defines __iter__ is automatically considered an Iterable:

12345678910111213141516
from collections.abc import Iterable # Custom class with __iter__ – no inheritance from Iterable class DataStream: def __init__(self, records): self._records = records def __iter__(self): return iter(self._records) stream = DataStream([{"id": 1}, {"id": 2}, {"id": 3}]) print(isinstance(stream, Iterable)) # True – __subclasshook__ recognized __iter__ for record in stream: print(record)

Combining __subclasshook__ with Abstract Methods

__subclasshook__ controls isinstance()/issubclass() checks, but does not enforce abstract methods on real subclasses. The two mechanisms are independent:

1234567891011121314151617181920212223242526
from abc import ABC, abstractmethod class Runnable(ABC): @abstractmethod def run(self): pass @classmethod def __subclasshook__(cls, subclass): if cls is Runnable: if any("run" in klass.__dict__ for klass in subclass.__mro__): return True return NotImplemented # Structural check passes – run() is present class BackgroundJob: def run(self): print("Running background job") print(isinstance(BackgroundJob(), Runnable)) # True # Real subclass still gets enforcement class BrokenJob(Runnable): pass # Missing run() job = BrokenJob() # TypeError – abstract method not implemented

register() vs __subclasshook__

question mark

What should __subclasshook__ return to signal that normal ABC membership lookup should proceed?

Selecteer het correcte antwoord

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 2. Hoofdstuk 4

Vraag AI

expand

Vraag AI

ChatGPT

Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.

Sectie 2. Hoofdstuk 4
some-alt