Is it possible to inherit from multiple classes that share a parent?
class A:
def __init__(self, a1, a2='a2'):
self.a1=a1
self.a2=a2
def report(self):
print('here are my attrs: ', self.a1, self.a2)
class B(A):
def __init__(self, b, *args, **kwargs):
self.b=b
A.__init__(self, *args, **kwargs)
class C(A):
def __init__(self, *args, c='c', **kwargs):
self.c=c
A.__init__(self, *args, **kwargs)
class D(B, C):
def __init__(self, *args, d='d', **kwargs):
self.d=d
super().__init__(self, *args, **kwargs)
If I try the above example I get:
TypeError: __init__() got multiple values for argument
I assume the issue arises due to *args
and **kwargs
from the shared parent class being duplicated when super()
is resolving the MRO.
For context, I am trying to create a class that inherits methods and attributes from two other classes that share a parent.
If this is possible, how do you reconcile the different classes __init__
constructor?
The reason why the interpreter complains about __init__
getting multiple values for argument b
is because you're calling B.__init__
from D.__init__
with both a positional argument corresponding to b
and a keyword argument of b
in **kwargs
with this statement:
super().__init__(self, *args, **kwargs)
When you call a method through super()
, self
is already implicitly passed for you as the first argument to the method so your explicit argument self
here actually becomes the next positional argument, b
.
Your code would work by removing self
from all calls to the __init__
method of the parent. Also note that you should call super().__init__
instead of A.__init__
in both B.__init__
and C.__init__
to make them cooperatively pass the call to the next __init__
method in the MRO:
class A:
def __init__(self, a1, a2='a2'):
self.a1 = a1
self.a2 = a2
def report(self):
print('here are my attrs:', self.a1, self.a2)
class B(A):
def __init__(self, b, *args, **kwargs):
print(kwargs)
self.b = b
super().__init__(*args, **kwargs)
class C(A):
def __init__(self, *args, c='c', **kwargs):
print(kwargs)
self.c = c
super().__init__(*args, **kwargs)
class D(B, C):
def __init__(self, *args, d='d', **kwargs):
print(kwargs)
self.d = d
super().__init__(*args, **kwargs)
D(a1=0, a2=1, b=2, c=3, d=4).report()
This outputs:
{'a1': 0, 'a2': 1, 'b': 2, 'c': 3}
{'a1': 0, 'a2': 1, 'c': 3}
{'a1': 0, 'a2': 1}
here are my attrs: 0 1