Multiple Inheritance with kwargs

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.


In this example B would have worked the same if it was defined as you say (point 1) and C is as is (and there is no other use of it).

As for point 2: A call to constructor of super() would indeed fail as indicated, if there were still keyword arguments left, e.g.:

c = C(a=1, b=2, c=3, d=4)
# -> TypeError: object.__init__() takes exactly one argument (the instance to initialize)

As the class B is (originally) written, it would be also OK if used in reverse order as you say, or if there was one (or) more super-class(es), e.g.:

class D:
    def __init__(self, d, **kwargs):
        super().__init__(**kwargs)
        self.d = d

class C(A,B,D):
    ...