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 :
my_class.__subclasses__
will return the classes, which subclass from my_classC.__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:
Your classes are the wrong way round in that
register
call; it would only make sense in this context to callBase.register(ModelA)
(not the other way round) in order to registerModelA
as a "virtual subclass" ofBase
.Calling
ModelA.register(Base)
is trying to registerBase
as a virtual subclass ofModelA
, butModelA
is already an actual subclass ofBase
, - which is why you're getting an inheritance cycle. You can't have classes X and Y inheriting from each other.However, as
ModelA
is explicitly a subclass ofBase
, you don't need to callregister
at all. You want either:class ModelA(Base):
...with no
register
call (hereModelA
is an actual subclass ofBase
), or:class ModelA:
...
Base.register(ModelA)(here
ModelA
is a standalone class, outsideBase
's inheritance hierarchy, but it is registered as a virtual subclass). Either/or - not both.In either case,
issubclass(ModelA, Base)
would beTrue
.__subclasses__()
doesn't pick up virtual subclasses, only actual ones - so if you want to use that, you should forget aboutregister()
and just makeModelA
a real subclass ofBase
(the first option above).(This is, to my mind, a wart with the whole ABC/
register
mechanism:issubclass()
might beTrue
but__subclasses__()
doesn't pick it up - nasty.)If you don't import the model containing
ModelA
at some point in your execution, it's never set up soModelA
won't show up inBase.__subclassess__()
anyway. This is probably why the dictionary inmain.py
is empty.A fix would be to add a line to
main.py
sayingimport models
, and havemodels/__init__.py
importmodel_a
andmodel_b
. Then whenmain
runs, it importsmodels
, which in turn importsmodel_a
andmodel_a
, executing the definitions ofModelA
andModelB
and adding them toBase
's class hierarchy.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
Set Bash Variable from Python Script
How to Send Http Requests to Flask Server
No Module Named 'Virtualenvwrapper'
How to Deploy a Perl/Python/Ruby Script Without Installing an Interpreter
Construct Pandas Dataframe from Items in Nested Dictionary
How to Convert a String to a Number If It Has Commas in It as Thousands Separators
Using Quotation Marks Inside Quotation Marks
How to Determine a Python Variable's Type
Class Method Differences in Python: Bound, Unbound and Static
What Is the Most Efficient Way to Loop Through Dataframes with Pandas
How to Parse a Yaml File in Python
How to Make Selenium Not Wait Till Full Page Load, Which Has a Slow Script
How Are Tuples Unpacked in for Loops
How to Enable Cors on Django Rest Framework
How to One Hot Encode in Python