5

I'm new to python and trying to get a list of the classes an object's class inherits from. I'm trying to do this using the bases attribute but I'm not having any success. Can someone please help me out?

def foo(C):
     print(list(C.__bases__))

class Thing(object):
    def f(self):
        print("Yo")

class Shape(Thing):
    def l(self):
        print("ain't no thang")

class Circle(Shape):
    def n(self):
        print("ain't no shape")

test = Circle()
foo(test)

4 Answers 4

6

Only classes have __bases__; class instances do not. You can get the class object through an instance's __class__: use foo(test.__class__) or foo(Circle).

Sign up to request clarification or add additional context in comments.

Comments

4

Use inspect, from documentation

Return a tuple of class cls’s base classes, including cls, in method resolution order. No class appears more than once in this tuple. Note that the method resolution order depends on cls’s type. Unless a very peculiar user-defined metatype is in use, cls will be the first element of the tuple.

>>> import inspect
>>> inspect.getmro(test.__class__)
(<class '__main__.Circle'>, <class '__main__.Shape'>, <class '__main__.Thing'>, <type 'object'>)
>>> 

This traverses up the inheritance hierarchy & prints all classes, including object. Pretty Cool eh ?

5 Comments

+1 since it returns a list of all of the classes. In order to get it to work with the OP's example, I believe it should be test.__class__ since test is an instance in his case?
yes it should be test.__class__, was in a hurry to answer :)
Assuming it's a new-style class, test.__class__.__mro__ should also work. The reason to use getmro is that it handles old-style classes as well. It first looks for __mro__, and if it doesn't find it, it assumes the class is an old-style class and recursively searches the __bases__ hierarchy. If you don't need that functionality, then you can avoid an import.
yes i forgot about that, thanks for pointing out. But my philosophy is, when there is a method in the core lib which does this (& also provides backward compatibility) why should I write my own.
I see your point -- certainly you're right importing getmro makes more sense than defining foo as above.
2
print '\n'.join(base.__name__ for base in test.__class__.__bases__)

Or, using the inspect module:

from inspect import getmro
print '\n'.join(base.__name__ for base in getmro(test))

Comments

1

Your implementation of foo works. But you need to pass a class to foo, not an instance.

In [1]: def foo(C):
   ...:          print(list(C.__bases__))
   ...:

In [2]: class Thing(object):
   ...:         def f(self):
   ...:                 print("Yo")
   ...:

In [3]: class Shape(Thing):
   ...:         def l(self):
   ...:                 print("ain't no thang")
   ...:

In [4]: class Circle(Shape):
   ...:         def n(self):
   ...:                 print("ain't no shape")
   ...:

In [5]: test = Circle()

In [6]: foo(test)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-7b85deb1beaa> in <module>()
----> 1 foo(test)

<ipython-input-1-acd1789d43a9> in foo(C)
      1 def foo(C):
----> 2          print(list(C.__bases__))
      3

AttributeError: 'Circle' object has no attribute '__bases__'

In [7]: foo(Thing)
[<type 'object'>]

In [8]: foo(Circle)
[<class '__main__.Shape'>]

In [9]: foo(Shape)
[<class '__main__.Thing'>]

1 Comment

Ah thank you all. Much appreciated. I didn't understand that objects didn't have bases

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.