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.dani...@acm.org
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to