I'm trying to figure out the multiple inheritance in Python, but all articles I find are limited to simple cases. Let's consider the following example:
class Vehicle:
def __init__(self, name: str) -> None:
self.name = name
print(f'Creating a Vehicle: {name}')
def __del__(self):
print(f'Deleting a Vehicle: {self.name}')
class Car(Vehicle):
def __init__(self, name: str, n_wheels: int) -> None:
super().__init__(name)
self.wheels = n_wheels
print(f'Creating a Car: {name}')
def __del__(self):
print(f'Deleting a Car: {self.name}')
class Boat(Vehicle):
def __init__(self, name: str, n_props: int) -> None:
super().__init__(name)
self.propellers = n_props
print(f'Creating a Boat: {name}')
def __del__(self):
print(f'Deleting a Boat: {self.name}')
class Amfibii(Car, Boat):
def __init__(self, name: str, n_wheels: int, n_props: int) -> None:
Car.__init__(self, name, n_wheels)
Boat.__init__(self, name, n_props)
print(f'Creating an Amfibii: {name}')
def __del__(self):
print(f'Deleting an Amfibii: {self.name}')
my_vehicle = Amfibii('Mazda', 4, 2)
I want to understand the order of calling constructors and destructors, as well as the correct and general use of the 'super' keyword. In the example above, I get the following error:
super().__init__(name)
TypeError:Boat.__init__()
missing 1 required positional argument: 'n_props'
How should I correctly call constructors of both parents, which have different sets of constructor arguments?
Thanks to the comments and the following article, I understood it. https://rhettinger.wordpress.com/2011/05/26/super-considered-super/
Regarding the constructors' arguments, they should be named. In this way, every level strips what it needs and passes it to the next one using super()
Every class calls super().__init__()
only once. The following classes in the MRO order are responsible for continuing the initialization.
The updated example:
class Vehicle:
def __init__(self, name: str) -> None:
self.name = name
print(f'Creating a Vehicle: {name}')
def go(self):
print('Somehow moving...')
assert not hasattr(super(), 'go')
class Car(Vehicle):
def __init__(self, n_wheels: int, **kwargs) -> None:
super().__init__(**kwargs)
self.wheels = n_wheels
print(f'Creating a Car: {self.name}')
def go(self):
print('Riding...')
super().go()
class Boat(Vehicle):
def __init__(self, n_props, **kwargs) -> None:
super().__init__(**kwargs)
self.propellers = n_props
print(f'Creating a Boat: {self.name}')
def go(self):
print('Swimming...')
super().go()
class Amfibii(Car, Boat):
def __init__(self, **kwargs) -> None:
super().__init__(**kwargs)
print(f'Creating an Amfibii: {self.name}')
def go(self):
print('Riding or swimming...')
super().go()
my_vehicle = Amfibii(name='Mazda', n_wheels=4, n_props=2)
my_vehicle.go()
It's a bit cumbersome (gently speaking), isn't it?
EDIT: I updated the code according co the comments.