1

I'm learning multiple inheritance of class

class A(): 
    def __init__(self, a): 
        super().__init__() 
        self.a = a                                                                                                                                             

class B(): 
    def __init__(self, b): 
        super().__init__() 
        self.b = b 
         
class C(A, B): 
    def __init__(self, a, b, c): 
        super().__init__(a, b) 
        self.c = c 

C(1, 2, 3) leads to error TypeError: __init__() takes 2 positional arguments but 3 were given

I wish it can initialize in order A->B->C, I still get stuck after looking up existed related questions

ComplicatedPhenomenon
  • 4,055
  • 2
  • 18
  • 45

2 Answers2

3

If you need to give specific arguments to specific superclasses, you'll need to do it explicitly:

class A(): 
    def __init__(self, a): 
        self.a = a                                                                                                                                             

class B(): 
    def __init__(self, b): 
        self.b = b 
         
class C(A, B): 
    def __init__(self, a, b, c): 
        A.__init__(self, a) 
        B.__init__(self, b)
        self.c = c

Note that you also can't do super().__init__() in the classes A and B anymore, because super doesn't actually invoke the superclass of the class it's "written in", but the next class up the Method Resolution Order.

Usually, code like this indicates bad design/a misuse of subclassing.


Alternatively, you can get around this by using keyword arguments:

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, a, b, c): 
        super().__init__(a=a, b=b)
        self.c = c
L3viathan
  • 26,748
  • 2
  • 58
  • 81
1

Make the base clases more flexible by having them pass extra *args on to the super call:

class A(): 
    def __init__(self, a, *args): 
        super().__init__(*args) 
        self.a = a
        

class B(): 
    def __init__(self, b, *args): 
        super().__init__(*args) 
        self.b = b 
      

class C(A, B): 
    def __init__(self, a, b, c): 
        super().__init__(a, b) 
        self.c = c 

>>> c = C(1,2,3)
>>> c.a
1
>>> c.b
2
>>> c.c
3

It would be even better to use keyword arguments in order not to rely on the mro:

class A(): 
    def __init__(self, a=None, **kwargs): 
        super().__init__(**kwargs) 
        self.a = a
        

class B(): 
    def __init__(self, b=None, **kwargs): 
        super().__init__(**kwargs) 
        self.b = b
      

class C(A, B): 
    def __init__(self, a, b, c): 
        super().__init__(a=a, b=b) 
        self.c = c 

Now, class C(B, A) will work just as expected.

user2390182
  • 72,016
  • 6
  • 67
  • 89