super
is indeed intended for this situation, but it only works if you use it consistently. If the base classes don't also all use super
it won't work, and unless the method is in object
you have to use something like a common base class to terminate the chain of super
calls.
class FooBase(object):
def foo(self): pass
class A(FooBase):
def foo(self):
super(A, self).foo()
print 'A.foo()'
class B(FooBase):
def foo(self):
super(B, self).foo()
print 'B.foo()'
class C(A, B):
def foo(self):
super(C, self).foo()
print 'C.foo()'
Reason for keeping the same base:
Without FooBase that implements foo but doesn't call super() the last class that does call super() will get an attribute error as there is no base method to call.
If there were separate base classes class A(AFooBase): and class B(BFooBase): the super() call in A would call the method in AFooBase and the method in B would never be called. When the base is common to all of the classes it goes to the end of the method resolution order and you can be certain that no matter how the classes are defined the base class method will be the last one called.