I got the following example code. I understand that the code is falling since super(A, self).__init__(attr_base1, attr_base2)
is calling the __init__
of B(Base)
, but I don't really understand why. Since I put A
in super(A, self)
, I thought that it should search for the parent class starting from A
. What should I do if I want A.init(self, attr1, "b1", "b2") to call in super for the Base
__init__
?
class Base(object):
def __init__(self, attr_base1, attr_base2):
self.attr_base1 = attr_base1
self.attr_base2 = attr_base2
def foo(self):
print ('A.foo()')
class A(Base):
def __init__(self, attr, attr_base1, attr_base2):
super(A, self).__init__(attr_base1, attr_base2)
self.attr1 = attr
class B(Base):
def __init__(self, attr):
self.attr2 = attr
def foo(self):
print ('B.foo()')
class C(A, B):
def __init__(self, attr1, attr2):
A.__init__(self, attr1, "b1", "b2")
A.__init__(self, attr2)
c = C(1, 2)
I would redefine all three classes to make them work better in a cooperative multiple-inheritance hierarchy. (See https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ for more information about the design choices made here.)
Some general rules for __init__
:
super().__init__
with the extra keyword arguments,
even if you are only statically inheriting from object
.__init__
class Base:
def __init__(self, *, attr_base1, attr_base2, **kwargs):
super().__init__(**kwargs)
self.attr_base1 = attr_base1
self.attr_base2 = attr_base2
def foo(self):
print ('A.foo()')
class A(Base):
def __init__(self, *, a_attr, **kwargs):
super().__init__(**kwargs)
self.attr1 = a_attr
class B(Base):
def __init__(self, *, b_attr, **kwargs):
super().__init__(**kwargs)
self.attr2 = b_attr
def foo(self):
print ('B.foo()')
class C(A, B):
def __init__(self, **kwargs):
# Override any explicitly passed values.
kwargs["attr_base1"] = "b1"
kwargs["attr_base2"] = "b2"
super().__init__(**kwargs)
c = C(a_attr=1, b_attr=2)
In this example,
C.__init__
is responsible for hard-coding the base-class attributes before delegating the actual initialization to A.__init__
.A.__init__
is responsible for extracting a_attr
from the keyword arguments and initializing the attribute attr1
before delegating the rest of the initialization to B.__init__
.B.__init__
is responsible for extracting b_attr
fro the keyword arguments and initializing the attribute attr2
before delegating the rest of the initialization to Base.__init__
.Base.__init__
is responsible for extracting attr_base1
and attr_base2
from the keyword arguments, and initializing the attributes attr_base1
and attr_base2
before delegating the rest of the initialization to object.__init__
.object.__init__
doesn't really do anything except produce an exception if any "unclaimed" keyword arguments get passed to it.