Consider the following snippet of python code
class A(object):
def __init__(self, a):
self.a = a
class B(A):
def __init__(self, a, b):
super(B, self).__init__(a)
self.b = b
class C(A):
def __init__(self, a, c):
super(C, self).__init__(a)
self.c = c
class D(B, C):
def __init__(self, a, b, c, d):
#super(D,self).__init__(a, b, c) ???
self.d = d
I am wondering how can I pass a
, b
and c
to corresponding base classes' constructors.
Well, when dealing with multiple inheritance in general, your base classes (unfortunately) should be designed for multiple inheritance. Classes B
and C
in your example aren't, and thus you couldn't find a proper way to apply super
in D
.
One of the common ways of designing your base classes for multiple inheritance, is for the middle-level base classes to accept extra args in their __init__
method, which they are not intending to use, and pass them along to their super
call.
Here's one way to do it in python:
# Multiple inheritance in Python 3
# Define class A with attribute a
class A:
def __init__(self, a):
self.a = a
def method_a(self):
print(f"Method from A: a = {self.a}")
# Define class B that inherits from A with additional attribute b
class B(A):
def __init__(self, b, **kwargs):
super().__init__(**kwargs) # Call A's __init__
self.b = b
def method_b(self):
print(f"Method from B: b = {self.b}")
# Define class C that inherits from A with additional attribute c
class C(A):
def __init__(self, c, **kwargs):
super().__init__(**kwargs) # Call A's __init__
self.c = c
def method_c(self):
print(f"Method from C: c = {self.c}")
# Define class D that inherits from both B and C with additional attribute d
class D(B, C):
def __init__(self, a, b, c, d):
super().__init__(a=a, b=b, c=c) # super() will follow the MRO
self.d = d
def method_d(self):
print(f"Method from D: d = {self.d}")
# Example usage
if __name__ == "__main__":
obj = D(a="Value from A", b="Value from B", c="Value from C", d="Value from D")
# Calling methods from A, B, C, and D
obj.method_a() # From A
obj.method_b() # From B
obj.method_c() # From C
obj.method_d() # From D
# Print the Method Resolution Order (MRO) for class D
print("\nMRO of class D:")
for cls in D.mro():
print(cls)
This can be viewed as disappointing, but that's just the way it is.