Python: Show all subclasses of a class

Just a lovely scroll.

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 recursive wrapper:

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

It yields and all subclasses and then recursively from their subclasses. It uses a set, seen, to avoid duplicates , which arise with 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.

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

Fin

Stay classy,

—Adam


Read my book Boost Your Django DX, freshly updated in November 2024.


Subscribe via RSS, Twitter, Mastodon, or email:

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

Related posts:

Tags: