How to Find All the Subclasses of a Class Given Its Name

How to find all the subclasses of a class given its name?

New-style classes (i.e. subclassed from object, which is the default in Python 3) have a __subclasses__ method which returns the subclasses:

class Foo(object): pass
class Bar(Foo): pass
class Baz(Foo): pass
class Bing(Bar): pass

Here are the names of the subclasses:

print([cls.__name__ for cls in Foo.__subclasses__()])
# ['Bar', 'Baz']

Here are the subclasses themselves:

print(Foo.__subclasses__())
# [<class '__main__.Bar'>, <class '__main__.Baz'>]

Confirmation that the subclasses do indeed list Foo as their base:

for cls in Foo.__subclasses__():
print(cls.__base__)
# <class '__main__.Foo'>
# <class '__main__.Foo'>

Note if you want subsubclasses, you'll have to recurse:

def all_subclasses(cls):
return set(cls.__subclasses__()).union(
[s for c in cls.__subclasses__() for s in all_subclasses(c)])

print(all_subclasses(Foo))
# {<class '__main__.Bar'>, <class '__main__.Baz'>, <class '__main__.Bing'>}

Note that if the class definition of a subclass hasn't been executed yet - for example, if the subclass's module hasn't been imported yet - then that subclass doesn't exist yet, and __subclasses__ won't find it.


You mentioned "given its name". Since Python classes are first-class objects, you don't need to use a string with the class's name in place of the class or anything like that. You can just use the class directly, and you probably should.

If you do have a string representing the name of a class and you want to find that class's subclasses, then there are two steps: find the class given its name, and then find the subclasses with __subclasses__ as above.

How to find the class from the name depends on where you're expecting to find it. If you're expecting to find it in the same module as the code that's trying to locate the class, then

cls = globals()[name]

would do the job, or in the unlikely case that you're expecting to find it in locals,

cls = locals()[name]

If the class could be in any module, then your name string should contain the fully-qualified name - something like 'pkg.module.Foo' instead of just 'Foo'. Use importlib to load the class's module, then retrieve the corresponding attribute:

import importlib
modname, _, clsname = name.rpartition('.')
mod = importlib.import_module(modname)
cls = getattr(mod, clsname)

However you find the class, cls.__subclasses__() would then return a list of its subclasses.

Python: find all classes which inherit from this one?

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.

How do you find all subclasses of a given class in Java?

There is no other way to do it other than what you described. Think about it - how can anyone know what classes extend ClassX without scanning each class on the classpath?

Eclipse can only tell you about the super and subclasses in what seems to be an "efficient" amount of time because it already has all of the type data loaded at the point where you press the "Display in Type Hierarchy" button (since it is constantly compiling your classes, knows about everything on the classpath, etc).

See all inherited classes in python

just combining the answerts from above :

  1. my_class.__subclasses__ will return the classes, which subclass from my_class

  2. C.__mro__ shows the inheritence hierarchy in your case :
    (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>)

  object
/ \
A B
\ /
C

In short, __subclasses__ goes down the object hierarchy ladder and the __mro__ goes up. Good luck :)

python: instaintiate all subclasses in a module along with their function output

The hard part was to find all the subclasses, because it uses the less known __subclasses__ special method. From that it is straightforward: instanciate an object for each subclass and call the process method on it:

final_result = []                      # prepare an empty list
for cls in A.__subclasses__(): # loop over the subclasses
x = cls() # instanciate an object
final_result.append(x.process()) # and append the result of the process method

But the Pythonic way would be to use a one line comprehension

final_result = [cls().process() for cls in A.__subclasses__()]

How to get in a superclass full names of all methods in subclasses that start with the same two letters in python

You can iterate over the subclasses of some class using the __subclasses__() method. You can check the namespace of the subclasses for attributes that start with "on_", so something to the effect of:

class Ur:
@classmethod
def get_all_on_methods(cls):
results = []
for klass in cls.__subclasses__():
for name, attribute in vars(klass).items():
if name.startswith("on_"):
results.append((attribute, klass))
return results

class Foo(Ur):
def on_index(self):
pass
def some_method(self):
pass

class Bar(Ur):
def on_spiking_intent(self):
pass
def another_method(self):
pass

This populates a list for illustration purposes, you could easily populate a dictionary or whatever you want instead.

Also, this gets any class attribute, so you might want to check if it is a method by using:

if callable(attribute) and name.startswith("on_"):
...

But that is up to you.

Here's the output you get in the above example:

In [2]: Ur.get_on_methods()
Out[2]:
[(<function __main__.Foo.on_index(self)>, __main__.Foo),
(<function __main__.Bar.on_spiking_intent(self)>, __main__.Bar)]

Getting all registered subclasses of an ABCMeta

I realise this is rather late, but in case it's helpful to anyone else who stumbles upon this...

You've got a few problems here:

  1. Your classes are the wrong way round in that register call; it would only make sense in this context to call Base.register(ModelA) (not the other way round) in order to register ModelA as a "virtual subclass" of Base.

  2. Calling ModelA.register(Base) is trying to register Base as a virtual subclass of ModelA, but ModelA is already an actual subclass of Base, - which is why you're getting an inheritance cycle. You can't have classes X and Y inheriting from each other.

  3. However, as ModelA is explicitly a subclass of Base, you don't need to call register at all. You want either:

    class ModelA(Base):
    ...

    with no register call (here ModelA is an actual subclass of Base), or:

    class ModelA:
    ...

    Base.register(ModelA)

    (here ModelA is a standalone class, outside Base's inheritance hierarchy, but it is registered as a virtual subclass). Either/or - not both.

    In either case, issubclass(ModelA, Base) would be True.

  4. __subclasses__() doesn't pick up virtual subclasses, only actual ones - so if you want to use that, you should forget about register() and just make ModelA a real subclass of Base (the first option above).

    (This is, to my mind, a wart with the whole ABC/register mechanism: issubclass() might be True but __subclasses__() doesn't pick it up - nasty.)

  5. If you don't import the model containing ModelA at some point in your execution, it's never set up so ModelA won't show up in Base.__subclassess__() anyway. This is probably why the dictionary in main.py is empty.

    A fix would be to add a line to main.py saying import models, and have models/__init__.py import model_a and model_b. Then when main runs, it imports models, which in turn imports model_a and model_a, executing the definitions of ModelA and ModelB and adding them to Base's class hierarchy.

  6. On your final line, you don't instantiate an instance of whatever class klass is pointing at; the line should be:

    klass().run()


Related Topics



Leave a reply



Submit