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?
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.
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__
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.
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?
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.
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__
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.