Reputation: 165252
Consider two classes that each have an existing shared function, but separate inheritance paths:
class ClazzA(SuperClazzX):
def foo(self):
return goo(super(SuperClazzX, self).foo())
class ClazzB(SuperClazzY):
def foo(self):
return goo(super(SuperClazzY, self).foo())
foo
is clearly a common function which can be extracted to a mixin, what is the right way to do so, such that the functionality remains even though a different super foo
is to be called?
Edit: I removed the other mixin, it was confusing and irrelevant.
Upvotes: 2
Views: 429
Reputation: 11781
EDIT: simpler code
Mixin has access to other bases of (future) child class, here C::Mixin::foo
has access to the other base of C
, namely C::Base::foo
. Authoritative explanation here.
class Base(object): # must be new-style class in py 2.x
def foo(self):
print "base foo called"
class Mixin(object):
def foo(self):
rv = super(Mixin, self).foo() # call actual implementation
# use rv
class C(Mixin, Base):
pass
C().foo()
base foo called
What this does:
self
is instance of C
, it's __mro__
is (Mixin, Base)super(Mixin, self)
, the resulting object retains bases (Base,).foo
attribute is resolved, this object finds it in BaseBase.foo
is invoked with original self
If you want custom control over implementation, you have access to your own bases, e.g.:
class Foo(...):
def foo(self):
print self.__class__.__bases__
Your mixin could look something like this, super-manual approach:
class Mixin(object):
def foo(self):
assert self.__class__ is not Mixin # no point calling directly
# find the other base
other = [b for b in self.__class__.__bases__ if b is not Mixin]
# what to do if there's more than 1 real base?
# pick base explicitly
base = other[1]
# call it,
return something(base.foo(self, some_args))
Upvotes: 1