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 ofC
, it's__mro__
is (Mixin, Base)- when Mixin calls
super(Mixin, self)
, the resulting object retains bases (Base,) - when
.foo
attribute is resolved, this object finds it in Base - thus
Base.foo
is invoked with originalself
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))