Python: Show all subclasses of a class

Just a lovely scroll.

Update (2024-08-02): Updated recursive_subclasses() to deduplicate with a set.

Update (2026-06-05): Updated recursive_subclasses() to deduplicate when a class is inherited from directly as well as via a subclass, changing the approach to an iterative one using a deque on the way.

class.__subclasses__() returns a list of the direct subclasses of a given class:

In [1]: class Base: pass
   ...: class Alpha(Base): pass

In [2]: Base.__subclasses__()
Out[2]: [__main__.Alpha]

This function picks up subclasses wherever they are defined. That can make it useful for tracking down code to edit, as I showed recently.

But __subclasses__() does not descend the inheritance hierarchy, so it does not return subclasses of subclasses:

In [1]: class Base: pass
   ...: class Alpha(Base): pass
   ...: class Beta(Alpha): pass

In [2]: Base.__subclasses__()
Out[2]: [__main__.Alpha]

To get all subclasses, use this wrapper:

from collections import deque


def recursive_subclasses(klass):
    """
    Yield all subclasses of the given class, per:
    https://adamj.eu/tech/2024/05/10/python-all-subclasses/
    """
    queue = deque(klass.__subclasses__())
    seen = set()
    while queue:
        subclass = queue.popleft()
        if subclass not in seen:
            seen.add(subclass)
            yield subclass
            queue.extend(subclass.__subclasses__())

It yields all subclasses and then recursively from their subclasses. It uses a set, seen, to avoid duplicates, which can arise from patterns like diamond-style inheritance.

For example:

In [4]: list(recursive_subclasses(Base))
Out[4]: [__main__.Alpha, __main__.Beta]

As recursive_subclasses() is a generator function, list() is required to get all the classes at once.

Fin

Stay classy,

—Adam


😸😸😸 Check out my new book on using GitHub effectively, Boost Your GitHub DX! 😸😸😸


Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: