Multiple inheritance - How to call method_x in InheritedBaseB from method_x in InheritedBaseA?

Scott David Daniels Scott.Daniels at Acm.Org
Fri Sep 4 12:23:43 EDT 2009


The Music Guy wrote:
> I have a peculiar problem that involves multiple inheritance and method calling.
> 
> I have a bunch of classes, one of which is called MyMixin and doesn't
> inherit from anything. MyMixin expects that it will be inherited along
> with one of several other classes that each define certain
> functionality.
... <code semi-example> ...
> This all appears fine at first, but ...
> One might be tempted to amend MyMixin's method_x so that it calls the
> parent's method_x before doing anything else:
> 
> class MyMixin(object):
>     def method_x(self, a, b, c):
>         super(MyMixin, self).method_x(a, b, c)
>         ...
> 
> ...but of course, that will fail with an AttributeError because
> MyMixin's only superclass is object, which does not have a method_x.

Here the fix below works.

> The only way I can think to solve the problem would be to implement a
> method_x for each Foo that calls the method_x for each of the bases:
...
> So, does anyone have an idea about how to remedy this, or at least
> work around it?

The diamond inheritance stuff is meant to allow you to deal with
exactly this issue.  If you define a class, MixinBase, with do-
nothing entries for all the methods you are inventing, and you
make all of your Mixin classes (and your main class) inherit
from MixinBase, you are guaranteed that all of the Mixins you
use will be earlier on the method resolution order (mro in the
docs) than MixinBase.  If the set of actual methods is small
and pervasive, I might even be tempted rename MixinBase to
"Object":

 >>> if 1:
     class MixinBase(object):
         '''Base for solving mixin strategy.

         Also a nice common place to describe the args and meaning.
         '''
         def method_x(self, a, b, c):
             '''Suitable docstring'''
             print 'MixinBase'

     class MyMixin(MixinBase):
         def method_x(self, a, b, c):
             super(MyMixin, self).method_x(a, b, c)
             print 'Mixin'
     class BaseA(MixinBase):
         def method_x(self, a, b, c):
             super(BaseA, self).method_x(a, b, c)
             print 'BaseA'
     class BaseB(MixinBase):
         pass
     class BaseC(MixinBase):
         def method_x(self, a, b, c):
             super(BaseC, self).method_x(a, b, c)
             print 'BaseC'
     class FooX(MyMixin, BaseA):
         def method_x(self, a, b, c):
             super(FooX, self).method_x(a, b, c)
             print 'FooX'
     class FooY(MyMixin, BaseB):
         pass
     class FooZ(MyMixin, BaseC):
         def method_x(self, a, b, c):
             super(FooZ, self).method_x(a, b, c)
             print 'FooZ'


 >>> FooZ().method_x(1,2,3)
MixinBase
BaseC
Mixin
FooZ
 >>> FooY().method_x(1,2,3)
MixinBase
Mixin
 >>> FooX().method_x(1,2,3)
MixinBase
BaseA
Mixin
FooX
 >>> BaseA().method_x(1,2,3)
MixinBase
BaseA
 >>>
--Scott David Daniels
Scott.Daniels at Acm.Org



More information about the Python-list mailing list