Multiple inheritance using super() in parent classes

Peter Otten __peter__ at web.de
Thu Feb 10 11:39:23 EST 2022


On 10/02/2022 09:20, Igor Basko wrote:
> Hi everyone,
> This is my first question here. Hope to get some clarification.
> Basically this question is about multiple inheritance and the usage of
> super().__init__ in parent
> classes.
>
> So I have two classes that inherit from the same base class.
> For example class B and class C inherit from A:
> class A:
>    def __init__(self, arg1):
>      pass
>
> class B(A):
>    def __init__(self, arg2):
>      super().__init__(arg2)
>
> class C(A):
>    def __init__(self, arg1, arg2):
>      super().__init__(arg2)
>
> Now I would like to create a new class D that inherits from B and C.
> One note, D is the only class that I am "allowed" to change. A, B and C are
> provided to me as is from an external package.
> class D(B, C):
>    def __init__(self):
>      B.__init__(self, 'arg1')
>      C.__init__(self, 'arg1', 'arg2')
>
> When I initialize D I get a TypeError.
> TypeError: __init__() missing 1 required positional argument: 'arg2'
> I get it from the invocation of super().__init__(arg2) inside the B class.
>
> As I understand it, the super() inside B tries to call the __init__ of
> class C,
> because of the multiple inheritance and the MRO that is constructed.
> But when B was implemented it wasn't aware of C and I assume,
> B shouldn't be aware of C in any case.

Even when you call the initializers explicitly you pass self, and that's
probably where the MRO is taken from. You can tweak that MRO by changing
the order of the parent classes:

class D(C, B): ...

However, this will call B.__init__() twice; therefore I'd stick to super():

class D(C, B):
     def __init__(self):
         super().__init__("arg1", "arg2")

> It gives me the feeling that I'm trying to implement some bad practice
> here, but I'm not sure why.

I have the feeling that your feeling is right ;)

> I would also like to hear your suggestions if there is a way to circumvent
> it. Maybe by the approach described here:
> https://rhettinger.wordpress.com/2011/05/26/super-considered-super/
> wrapping B and C in some Adapter class.

A quick glance at that page suggests that the adapter translates the
base class into an attribute -- which is what I would have suggested,
too. Using has-a instead of is-a relations is generally something to
consider seriously before jumping into multiple inheritance. The details
may depend on the actual use case which is hidden behind your A, B, C,
and D abstraction...



More information about the Python-list mailing list