views:

174

answers:

4

Is there anyway to discover the base class of a class in Python?

For given the following class definitions:

class A:
   def speak(self):
      print "Hi"

class B(A):
   def getName(self):
      return "Bob"

If I received an instance of an object I can easily work out that it is a B by doing the following:

instance = B()
print B.__class__.__name__

Which prints the class name 'B' as expected.

Is there anyway to discover that the instance of an object inherits from a base class as well as the actual class?

Or is that just not how objects in Python work?

+5  A: 
b = B()
b.__class__
b.__class__.__base__
b.__class__.__bases__
b.__class__.__base__.__subclasses__()

I strongly recommend checking out ipython and use the tab completion :-)

ndim
Interestingly, ipython doesn't see __bases__, but evaluating it is ok. I guess __base__ doesn't exist in 2.5, since that's no good for me.
Jonathan Feinberg
I'd pay close attention to the version specific Python docs when really using interfaces which are that close to the Python core functionality. That should give you an idea of whether __base__ or __bases__ are to be preferred.http://docs.python.org/library/stdtypes.html only talks about __bases__.
ndim
Oh, and I am running Python 2.6 (for the record).
ndim
A: 

If instead of discovery of the baseclass (i.e reflection) you know the desired class in advance you could use the following built in functions

eg:

# With classes from original Question defined
>>> instance = A()
>>> B_instance = B()
>>> isinstance(instance, A)
True
>>> isinstance(instance, B)
False
>>> isinstance(B_instance, A) # Note it returns true if instance is a subclass
True
>>> isinstance(B_instance, B)
True
>>> issubclass(B, A)
True

isinstance( object, classinfo) Return true if the object argument is an instance of the classinfo argument, or of a (direct or indirect) subclass thereof. Also return true if classinfo is a type object and object is an object of that type. If object is not a class instance or an object of the given type, the function always returns false. If classinfo is neither a class object nor a type object, it may be a tuple of class or type objects, or may recursively contain other such tuples (other sequence types are not accepted). If classinfo is not a class, type, or tuple of classes, types, and such tuples, a TypeError exception is raised. Changed in version 2.2: Support for a tuple of type information was added.

issubclass( class, classinfo) Return true if class is a subclass (direct or indirect) of classinfo. A class is considered a subclass of itself. classinfo may be a tuple of class objects, in which case every entry in classinfo will be checked. In any other case, a TypeError exception is raised. Changed in version 2.3: Support for a tuple of type information was added.

Tom Leys
+3  A: 

The inspect module is really powerful also:

>>> import inspect

>>> inst = B()
>>> inspect.getmro(inst.__class__)
(<class __main__.B at 0x012B42A0>, <class __main__.A at 0x012B4210>)
Ned Batchelder
+1  A: 

Another way to get the class hierarchy is to access the mro attribute:

class A(object):
    pass
class B(A):
    pass
instance = B()
print(instance.__class__.__mro__)
# (<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)

Note that in Python 2.x, you must use "new-style" objects to ensure they have the mro attribute. You do this by declaring

class A(object):

instead of

class A():

See http://www.python.org/doc/newstyle/ and http://www.python.org/download/releases/2.3/mro/ for more info new-style objects and mro (method resolution order).

In Python 3.x, all objects are new-style objects, so you can use mro and simply declare objects this way:

class A():
unutbu