Final class user might want to create a a class composed from Base
and Mixin
(Mixin
provides additional common functionality over a 3rd party library classes).
But the Mixin.__init__
is not called when used as below. Only Base.__init__
is called:
>>> class Base(object): #3rd party library class
... def __init__(self): print "Base"
...
>>> class Mixin(object): #my features useful as addendum for a few classes
... def __init__(self): print "Mixin"
...
>>> class C(Base, Mixin): pass
...
>>> c = C()
Base
How to enforce calling both Mixin.__init__
and Base.__init__
in this scenario without requiring the user to remember to put a constructor with super()
call in C class?
>>> class Base(object):
... def __init__(self): print "Base"
...
>>> class Mixin(object):
... def __init__(self): print "Mixin"
...
>>> class C(Base, Mixin):
... #easy to forget to add constructor
... def __init__(self): super(C, self).__init__()
...
>>> c = C()
Base
Mixin
Python doesn't chain any method calls like this automatically, so you need to be disciplined and use cooperative inheritance correctly. If one class uses super
, then all classes must use super
. (This is a simple case, since none of the overriden __init__
methods add any additional arguments. If they did, you would need to do some work to ensure that object.__init__
never received additional arguments once it was called.)
Read https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ before continuing.
class Base(object):
def __init__(self):
print "Base"
super(Base, self).__init__()
class Mixin(object):
def __init__(self):
print "Mixin"
super(Mixin, self).__init__()
class C(Base, Mixin):
pass
c = C()
(This is also a perfect example of why you need to understand how super
works, and not treat it as simple indirect reference to your class's base class.)
If you can't modify Base
or Mixin
to use super
, then you'll need to define wrappers around them that can. The linked article explains how.