Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Inheritance with kwargs

Problem

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

Questions

  1. Since the method resolution order is (__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
  1. Isn't 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)

  1. Is this a safeguard for if C was defined as class C(B, A) instead of class C(A, B)?
like image 489
Josmoor98 Avatar asked Mar 02 '20 19:03

Josmoor98


1 Answers

Consider how you might instantiate C:

c = C(a=3, b=5, c=9)

C.__init__ gets all the keyword arguments, but only uses the one for its own parameter c. The rest are passed on for the next __init__ method in the chain. In this case, that's A.__init__, which "pulls out" the argument for a and passes b on to B.__init__. B uses that and passes on the (now-empty) set of keyword arguments to the next method, object.__init__. Because all keyword arguments have been "claimed" and processed by other classes, object.__init__ succeeds.

Because of how the MRO is constructed, classes that properly use super() guarantee collectively that **kwargs will be empty by the time object.__init__ is called.

like image 159
chepner Avatar answered Oct 10 '22 03:10

chepner