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

ryles rylesny at gmail.com
Sun Sep 6 01:49:21 CEST 2009


On Sep 4, 6:01 am, The Music Guy <music... at alphaios.net> 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. It defines method_x, which it assumes will also be
> defined in the other class that MyMixin ends up getting inherited
> with. For example,
>
> class MyMixin(object):
>     def method_x(self, a, b, c):
>         ...
>
> class BaseA(object):
>     def method_x(self, a, b, c):
>         ...
>
> class BaseB(object):
>     def method_x(self, a, b, c):
>         ...
>
> class BaseC(object):
>     def method_x(self, a, b, c):
>         ...
>
> class FooX(MyMixin, BaseA):
>     ...
>
> class FooY(MyMxin, BaseB):
>     ...
>
> class FooZ(MyMixin, BaseC):
>     ...
>
> This all appears fine at first, but there is a problem: Each Foo's
> method_x must call the method_x of MyMixin as well as the method_x of
> each respective Foo's second base class. One cannot simply call
> FooN.method_x, because that will only call MyMixin.method_x and not
> that of the other base.
>
> 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.
>
> 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:
>
> class FooX(MyMixin, BaseA):
>     def method_x(self, a, b, c):
>         MyMixin.method_x(self, a, b, c)
>         BaseA.method_x(self, a, b, c)
>
> class FooY(MyMxin, BaseB):
>     def method_x(self, a, b, c):
>         MyMixin.method_x(self, a, b, c)
>         BaseB.method_x(self, a, b, c)
>
> class FooZ(MyMixin, BaseC):
>     def method_x(self, a, b, c):
>         MyMixin.method_x(self, a, b, c)
>         BaseC.method_x(self, a, b, c)
>
> The problem with this solution is that method_x has to be explicitly
> created for each Foo, even though they all do just about the same
> thing, which kind of defeats the purpose of using multiple inheritance
> in this situation. Besides that, I just don't like it!
>
> So, does anyone have an idea about how to remedy this, or at least
> work around it?

Hopefully I've interpreted your requirement correctly.

In this particular case a workaround is to use super() in your base
classes and then have your concrete classes inherit from the base
*before* the mixin:

class MyMixin(object):
    def method_x(self, a, b, c):
        print "MyMixin"

class BaseA(object):
    def method_x(self, a, b, c):
        print "BaseA"
        super(BaseA, self).method_x(a, b, c)

class FooX(BaseA, MyMixin):
    pass

FooX().method_x(1, 2, 3)

BaseA
MyMixin


And if you want to define method_x() in FooX, then simply have that
use super() as well.



More information about the Python-list mailing list