Python: find all classes which inherit from this one?

PythonInheritance

Python Problem Overview


Is there any way in python to query a namespace for classes which inherit from a particular class? Given a class widget I'd like to be able to call something like inheritors(widget) to get a list of all my different kinds of widget.

Python Solutions


Solution 1 - Python

You want to use Widget.__subclasses__() to get a list of all the subclasses. It only looks for direct subclasses though so if you want all of them you'll have to do a bit more work:

def inheritors(klass):
    subclasses = set()
    work = [klass]
    while work:
        parent = work.pop()
        for child in parent.__subclasses__():
            if child not in subclasses:
                subclasses.add(child)
                work.append(child)
    return subclasses

N.B. If you are using Python 2.x this only works for new-style classes.

Solution 2 - Python

You can track inheritance with your own metaclass

import collections

class A(object):
    class __metaclass__(type):
        __inheritors__ = defaultdict(list)

        def __new__(meta, name, bases, dct):
            klass = type.__new__(meta, name, bases, dct)
            for base in klass.mro()[1:-1]:
                meta.__inheritors__[base].append(klass)
            return klass

class B(A):
    pass

class C(B):
    pass

>>> A.__inheritors__
defaultdict(<type 'list'>, {<class '__main__.A'>: [<class '__main__.B'>, <class '__main__.C'>], <class '__main__.B'>: [<class '__main__.C'>]})

Anything that is inherited from A or it's derived classes will be tracked. You will get full inheritance map when all the modules in your application are loaded.

Solution 3 - Python

You have to walk through all objects in the global namespace (globals()) and check if the related object/class is a subclass of the some other class (check the Python docs for issubclass()).

Solution 4 - Python

# return list of tuples (objclass, name) containing all subclasses in callers' module
def FindAllSubclasses(classType):
    import sys, inspect
    subclasses = []
    callers_module = sys._getframe(1).f_globals['__name__']
    classes = inspect.getmembers(sys.modules[callers_module], inspect.isclass)
    for name, obj in classes:
        if (obj is not classType) and (classType in inspect.getmro(obj)):
            subclasses.append((obj, name))
    return subclasses

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkdtView Question on Stackoverflow
Solution 1 - PythonDuncanView Answer on Stackoverflow
Solution 2 - PythonImranView Answer on Stackoverflow
Solution 3 - PythonAndreas JungView Answer on Stackoverflow
Solution 4 - PythonformiaczekView Answer on Stackoverflow