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

Scott David Daniels Scott.Daniels at Acm.Org
Fri Sep 11 17:53:11 CEST 2009


The Music Guy wrote:
...
> 
> def main():
>     ...
> 
> class MyMixin(object):
This is a mistake.  If Mixins inherit from CommonBase as well, no
order of class definition can catch you out.
If it doesn't, you can get yourself in trouble.

>     def method_x(self, a, b, c):
>         super(MyMixin, self).method_x(a, b, c)
>         print "MyMixin.method_x(%s, %s, %s, %s)" % (repr(self),
> repr(a), repr(b), repr(c))
> 
> class CommonBase(object):
>     def method_x(self, a, b, c):
>         print "CommonBase.method_x(%s, %s, %s, %s)" % (repr(self),
> repr(a), repr(b), repr(c))
> 
> class BaseA(CommonBase):
>     ...

Redoing this example for small prints:

def main():
     for n, class_ in enumerate(
             (BaseA, BaseB, BaseC,
              FooV, FooW, FooX, FooY, FooZ,
              BarW, BarX, BarY, BarZ)):
         instance = class_()
         instance.method_x(n, n * '-', hex(n*13))
         print

class CommonBase(object):
     def method_x(self, a, b, c):
         # really, %r is the way to go.
         print "CommonBase.method_x(%r, %r, %r, %r)" % (self, a, b, c)

     def __repr__(self):
         # Just so we have a more compact repr
         return '%s.%s' % (self.__class__.__name__, id(self))

class Mixin(CommonBase):
     def method_x(self, a, b, c):
         super(Mixin, self).method_x(a, b, c)
         print "Mixin",

class MyMixin(CommonBase):
     def method_x(self, a, b, c):
         super(MyMixin, self).method_x(a, b, c)
         print "MyMixin",

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

class BaseB(CommonBase):
     def method_x(self, a, b, c):
         super(BaseB, self).method_x(a, b, c)
         print "BaseB",

class BaseC(CommonBase):
     pass

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

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

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",

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

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

class BarY(BaseB, MyMixin):
     def method_x(self, a, b, c):
         super(BarY, self).method_x(a, b, c)
         print "BarY",

class BarZ(BaseB, Mixin):
     def method_x(self, a, b, c):
         super(BarZ, self).method_x(a, b, c)
         print "BarZ",


 >>> main() # prints
CommonBase.method_x(BaseA.18591280, 0, '', '0x0')
BaseA
...
CommonBase.method_x(FooZ.18478384, 7, '-------', '0x5b')
MyMixin FooZ
CommonBase.method_x(BarW.18480592, 8, '--------', '0x68')
MyMixin BaseA Mixin BarW
...


If you make of Mixin and MyMixin inherit from object you get:

CommonBase.method_x(BaseA.18613328, 0, '', '0x0')
BaseA
...
CommonBase.method_x(FooZ.18480592, 7, '-------', '0x5b')
MyMixin FooZ
CommonBase.method_x(BarW.18591280, 8, '--------', '0x68')
BaseA Mixin BarW
...

Note that in the BarW case (with object), not all mixins are called.

--Scott David Daniels
Scott.Daniels at Acm.Org



More information about the Python-list mailing list