List all base classes in a hierarchy of given class?

88,004

Solution 1

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

Solution 2

See the __bases__ property available on a python class, which contains a tuple of the bases classes:

>>> def classlookup(cls):
...     c = list(cls.__bases__)
...     for base in c:
...         c.extend(classlookup(base))
...     return c
...
>>> class A: pass
...
>>> class B(A): pass
...
>>> class C(object, B): pass
...
>>> classlookup(C)
[<type 'object'>, <class __main__.B at 0x00AB7300>, <class __main__.A at 0x00A6D630>]

Solution 3

inspect.getclasstree() will create a nested list of classes and their bases. Usage:

inspect.getclasstree(inspect.getmro(IOError)) # Insert your Class instead of IOError.

Solution 4

you can use the __bases__ tuple of the class object:

class A(object, B, C):
    def __init__(self):
       pass
print A.__bases__

The tuple returned by __bases__ has all its base classes.

Solution 5

According to the Python doc, we can also simply use class.__mro__ attribute or class.mro() method:

>>> class A:
...     pass
... 
>>> class B(A):
...     pass
... 
>>> B.__mro__
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
>>> A.__mro__
(<class '__main__.A'>, <class 'object'>)
>>> object.__mro__
(<class 'object'>,)
>>>
>>> B.mro()
[<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
>>> A.mro()
[<class '__main__.A'>, <class 'object'>]
>>> object.mro()
[<class 'object'>]
>>> A in B.mro()
True

Share:
88,004

Related videos on Youtube

Sridhar Ratnakumar
Author by

Sridhar Ratnakumar

Updated on September 14, 2021

Comments

  • Sridhar Ratnakumar
    Sridhar Ratnakumar over 2 years

    Given a class Foo (whether it is a new-style class or not), how do you generate all the base classes - anywhere in the inheritance hierarchy - it issubclass of?

  • Sridhar Ratnakumar
    Sridhar Ratnakumar over 14 years
    This may introduce duplicates. And this is why the documentation for getmro explicitly says "No class appears more than once in this tuple"?
  • rbp
    rbp over 10 years
    Doesn't work for pyobjc classes :( File "/Users/rbp/Projects/zzzzzzz/macmdtypes.py", line 70, in coerce print inspect.getmro(path) File "/System/Library/Frameworks/Python.framework/Versions/2.7/li‌​b/python2.7/inspect.‌​py", line 348, in getmro searchbases(cls, result) File "/System/Library/Frameworks/Python.framework/Versions/2.7/li‌​b/python2.7/inspect.‌​py", line 339, in _searchbases for base in cls.__bases_: AttributeError: 'NSTaggedDate' object has no attribute '__bases'
  • esmit
    esmit almost 9 years
    @rbp I suspect that you had the same problem that I encountered: you were trying to do inspect.getmro(obj) instead of inspect.getmro(type(obj)).
  • Bob Stein
    Bob Stein about 8 years
    Caution, __bases__ only goes up one level. (As your recursive utility implies, but a cursory glance at the example might not pick up on that.)
  • penguin359
    penguin359 over 7 years
    Ooh, nice. And for even nicer output, use pprint! python -c 'import inspect; from pprint import pprint as pp; pp(inspect.getclasstree(inspect.getmro(IOError)))'
  • Boris Verkhovskiy
    Boris Verkhovskiy over 4 years
    If your class inherits from a class that inherits from a class, only the first part of the chain will be in its __bases__
  • Temperosa
    Temperosa almost 4 years
    Simple and clean without importing a whole module for a single function.
  • DavidW
    DavidW over 2 years
    @Temperosa it maybe be simple and clean but it's wrong
  • ssc
    ssc over 2 years
    Same thing seems to apply in my case as in @esmit's comment on the answer currently below this one: type.mro(my_obj) fails with TypeError: descriptor 'mro' for 'type' objects doesn't apply to a 'my_obj' object; type.mro(type(my_obj)) works. Not sure if that's relevant: my_obj is an instance of a Pydantic model.