Is there a standard function to iterate over base classes?

Question:

I would like to be able to iterate over all the base classes, both direct and indirect, of a given class, including the class itself. This is useful in the case where you have a metaclass that examines an internal Options class of all its bases.

To do this, I wrote the following:

def bases(cls):
    yield cls
    for direct_base in cls.__bases__:
        for base in bases(direct_base):
            yield base

Is there a standard function to do this for me?

Asked By: Conley Owens

||

Answers:

There is a method that can return them all, in Method Resolution Order (MRO): inspect.getmro. See here:

http://docs.python.org/library/inspect.html#inspect.getmro

It returns them as a tuple, which you can then iterate over in a single loop yourself:

import inspect
for base_class in inspect.getmro(cls):
    # do something

This has the side benefit of only yielding each base class once, even if you have diamond-patterned inheritance.

Answered By: Amber

I don’t know exactly if it is what you’re looking for, but have a look at someclass.__mro__, mro being Method Resolution Order

http://docs.python.org/library/stdtypes.html?highlight=mro#class.__mro__

Answered By: knitti

Amber has the right answer for the real world, but I’ll show one correct way to do this. Your solution will include some classes twice if two base classes themselves inherit from the same base class.

def bases(cls):
    classes = [cls]
    i = 0
    while 1:
        try:
            cls = classes[i]
        except IndexError:
            return classes
        i += 1
        classes[i:i] = [base for base in cls.__bases__ if base not in classes] 

The only slightly tricky part is where we use the slice. That’s necessary to perform this sort of depth first search without using recursion. All it does is take the base classes of the class currently being examined and insert them immediately after it so that the first base class is the next class examined. A very readable solution (that has it’s own ugliness) is available in the implementation of inspect.getmro in the standard library.

Answered By: aaronasterling
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.