Python: find all classes which inherit from this one?
Question:
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.
Answers:
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()).
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.
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.
# 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
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.
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()).
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.
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.
# 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