List All Base Classes in a Hierarchy of Given Class

List all base classes in a hierarchy of given class?

inspect.getmro(cls) works for both new and old style classes and returns the same as NewClass.mro(): a list of the class and all its ancestor classes, in the order used for method resolution.

>>> class A(object):
>>> pass
>>>
>>> class B(A):
>>> pass
>>>
>>> import inspect
>>> inspect.getmro(B)
(<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)

How do I inspect a Python's class hierarchy?

Hit f4 with class name highlighted to open hierarchy view.

Visual Studio: How do I show all classes inherited from a base class?

Sure, Resharper can do this. And much more.

Just right click on type name in any place and choose "Go To Inheritor" in context menu.
"Go To Inheritor" can be also applied to method for navigating to overrides and an interface method's implementations. For an interface you could call "Find Usages Advanced" again, just right click) where to find all extendings and implementations. For a type - derived types.
And my favorite feature - click with holding Control on any type/method for navigating to its declaration.

I think it's a must-have tool for .net developers.


In Resharper 9.2, on any type in source code, rt-click "Find Usage Advanced", select Find="Derived" and Scope="Solutions and Libraries".

For example, to find all inheritors (both in the library and your code) of some base class in an included DLL from any vendor, declare a variable in your code with that base class. Then right-click on that base class name you just typed.

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.

How do I get an overview of the Python hierarchy of types/classes?

Just because something is a type doesn't mean you have a reference to that type in the global namespace. This is the case with dict_keys. e.g.

>>> inspect.getmro(type({}.viewkeys()))  # using python2.x :-(
(<type 'dict_keys'>, <type 'object'>)

So it does have an MRO, and it is inspectable -- You just didn't have a handle on the dict_keys type before now.

Note that the MRO can be a bit deceiving:

>>> import collections
>>> issubclass(list, collections.Iterable)
True

so we see that list at least thinks that it is a subclass of collections.Iterable even though you won't find it in the MRO. This is because collections.Iterable actually registers itself using the abc module.

I think that this is one of the basic differences between python and java. In python, you typically care more about the interface the object provides rather than the actual type and inheritance tree. At some level this statement may seem a bit pedantic -- After all, you need to know the inheritance tree to know the interface an object provides. But the fact that we work in interfaces is exactly why tuple, list and generator objects can be iterated over despite not having a real common base class (collections.Iterable doesn't count as it is a virtual base class) above object (which can't be iterated over).

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).

Class design to avoid need for list of base classes

But what if I will need the managing class to give me all objects of
type DerivedA?

Is this an indicator of a bad class design because I have the need to
perform actions only on a subset of the class hierarchy?

More likely yes than no. If you often need to do this, then it makes sense to question whether the hierarchy makes sense. In that case, you should separate this into two unrelated lists.

Another possible approach is to also handle it through virtual methods, where e.g. DeriveB will have a no-op implementation for methods which don't affect that. It is hard to tell without knowing more information.

Traverse a class hierarchy from base to all descendants

Here's an example. This method will return all subclasses descending from the class you send the message to.

@interface NSObject (Debugging)

+ (NSArray *) allSubclasses;

@end

@implementation NSObject (Debugging)

+ (NSArray *) allSubclasses
{
Class myClass = [self class];
NSMutableArray *mySubclasses = [NSMutableArray array];

unsigned int numOfClasses;
Class *classes = objc_copyClassList(&numOfClasses);
for (unsigned int ci = 0; ci < numOfClasses; ci++) {
// Replace the code in this loop to limit the result to immediate subclasses:
// Class superClass = class_getSuperclass(classes[ci]);
// if (superClass == myClass)
// [mySubclasses addObject: classes[ci]];
Class superClass = classes[ci];
do {
superClass = class_getSuperclass(superClass);
} while (superClass && superClass != myClass);

if (superClass)
[mySubclasses addObject: classes[ci]];
}
free(classes);

return mySubclasses;
}

@end

Modify it as needed, make recursive calls, etc.

Find all parent types (both base classes and interfaces)

More general solution:

public static bool InheritsFrom(this Type type, Type baseType)
{
// null does not have base type
if (type == null)
{
return false;
}

// only interface or object can have null base type
if (baseType == null)
{
return type.IsInterface || type == typeof(object);
}

// check implemented interfaces
if (baseType.IsInterface)
{
return type.GetInterfaces().Contains(baseType);
}

// check all base types
var currentType = type;
while (currentType != null)
{
if (currentType.BaseType == baseType)
{
return true;
}

currentType = currentType.BaseType;
}

return false;
}

Or to actually get all parent types:

public static IEnumerable<Type> GetParentTypes(this Type type)
{
// is there any base type?
if (type == null)
{
yield break;
}

// return all implemented or inherited interfaces
foreach (var i in type.GetInterfaces())
{
yield return i;
}

// return all inherited types
var currentBaseType = type.BaseType;
while (currentBaseType != null)
{
yield return currentBaseType;
currentBaseType= currentBaseType.BaseType;
}
}


Related Topics



Leave a reply



Submit