You can always access the super-classes of a class by looking in the __bases__
attribute for that class. Given three simple classes A
, B
, C
(which for Py2.7
must inherit from object
) :
class A:
def foo():
pass
def bar():
pass
class B:
def biz(): pass
class C(A, B):
pass
You can then iterate through the __bases__
for C
and check whether an attribute, function foo
(for example), exists in one of these classes.
To do this you can check for membership of foo
in the __dict__
that holds the names for each class object in __bases__
:
for base in C.__bases__:
if 'foo' in base.__dict__:
print("Attribute: '{}' defined in {}".format("foo", base))
Which prints:
Attribute: 'foo' defined in <class '__main__.A'>
For a more complete and general view:
# get all attributes of class C
vars = [classVar for classVar in dir(C) if not classVar.startswith('__')]
# iterate through all bases:
for base in C.__bases__:
for attr in vars:
if attr in base.__dict__:
print("Attribute: '{}' defined in {}".format(attr, base))
Which returns:
Attribute: 'bar' defined in <class '__main__.A'>
Attribute: 'foo' defined in <class '__main__.A'>
Attribute: 'biz' defined in <class '__main__.B'>
For all classes in the chain of inheritance you can switch __bases__
to __mro__
which indicates the method resolution order; a tuple of objects python searches when trying to resolve attribute references.
If we add a function to class C
and make another class D
that inherits from C
:
class C(A, B):
def another(): pass
class D(C): pass
To get a view of where each function is defined, just switch __bases__
with __mro__
in the loop:
# hold D's attributes (functions names, variables.)
attrs = [var for var in dir(D) if not var.startswith('__')]
# vars contents: ['another', 'bar', 'biz', 'foo']
for base in D.__mro__:
for attr in attrs:
if attr in base.__dict__:
print("Attribute: '{}' defined in {}".format(attr, base))
Now, this follows the mro
tuple (equal to (__main__.D, __main__.C, __main__.A, __main__.B, object)
in this specific case) and yields a similar output:
Attribute: 'another' defined in <class '__main__.C'>
Attribute: 'bar' defined in <class '__main__.A'>
Attribute: 'foo' defined in <class '__main__.A'>
Attribute: 'biz' defined in <class '__main__.B'>