I came across this code in Object Oriented Programming by Dusty Phillips (simplified for brevity) and I unsure about a specific part of this definition.
class A:
def __init__(self, a, **kwargs):
super().__init__(**kwargs)
self.a = a
class B:
def __init__(self, b, **kwargs):
super().__init__(**kwargs)
self.b = b
class C(A, B):
def __init__(self, c, **kwargs):
super().__init__(**kwargs)
self.c = c
(__main__.C, __main__.A, __main__.B, object)
, could class B
be defined in the following way instead?class B:
def __init__(self, b):
self.b = b
super().__init__(**kwargs)
in class B
redundant, since any surplus kwargs
passed to C
will be passed to object
, raising?TypeError: object.__init__() takes exactly one argument (the instance to initialize)
C
was defined as class C(B, A)
instead of class C(A, B)
?Since the method resolution order is
(__main__.C, __main__.A, __main__.B, object)
, couldclass B
be defined in the following way instead?
No, because then this would fail:
class D:
def __init__(self, d, **kwargs):
self.d = d
super().__init__(**kwargs)
class E(C, D):
def __init__(self, e, **kwargs):
self.e = e
super().__init__(**kwargs)
The MRO of E
is (E, C, A, B, D, object)
, so B
must call super().__init__
otherwise D.__init__
won't be called.
Isn't
super().__init__(**kwargs)
inclass B
redundant, since any surpluskwargs
passed toC
will be passed toobject
, raising?
No, because the surplus kwargs
will go to D.__init__
in the above example. But even without that, it is not redundant to raise an error when you call a constructor with too many arguments; it is desirable to have an error message informing you about your incorrect code, rather than for the mistake to go undetected.
Is this a safeguard for if
C
was defined asclass C(B, A)
instead ofclass C(A, B)
?
In some sense, sure; but really it's a safeguard for B
occurring in any class hierarchy, so long as the other classes in the hierarchy follow the same rule of calling super().__init__(**kwargs)
.