I am struggling with the inheritance from two parents. I want to inherit from both the "super car" and the "cargo car" in order to be able to create a "super cargo car". When I call the code from below, I get:
"TypeError: __init __ () missing 1 required positional argument: 'capacity'"
class Car:
def __init__(self, brand, colour):
self.brand = brand
self.colour = colour
class SuperCar(Car):
def __init__(self, brand, colour, max_speed):
super().__init__(brand, colour)
self.max_speed = max_speed
def introduce_yourself(self):
statement = f"My colour is {self.colour} and my max speed is {self.max_speed}"
return statement
class CargoCar(Car):
def __init__(self, brand, colour, capacity):
super().__init__(brand, colour)
self.capacity = capacity
def introduce_yourself(self):
statement = f"My colour is {self.colour} and my capacity is {self.capacity} KG"
return statement
class SuperCargoCar(SuperCar, CargoCar):
def __init__(self, brand, colour, max_speed, capacity ):
super().__init__(brand, colour, max_speed)
self.capacity = capacity
def introduce_yourself(self):
super().introduce_yourself()
statement = f'My colour is {self.colour}, my max speed is {self.max_speed} ' \
f'and my capacity is {self.capacity} KG'
return statement
super_cargo_car = SuperCargoCar(brand="Volvo", colour="Green", max_speed=200, capacity=5000)
print(super_cargo_car.introduce_yourself())```
CodePudding user response:
As both of your SuperCar
and CargoCar
classes inherit from Car
class it results in an ambiguous mro
.
Fix it the following way:
class Car:
def __init__(self, brand, colour):
self.brand = brand
self.colour = colour
class SuperCar(Car):
def __init__(self, brand, colour, max_speed):
super().__init__(brand, colour)
self.max_speed = max_speed
def introduce_yourself(self):
statement = f"My colour is {self.colour} and my max speed is {self.max_speed}"
return statement
class CargoCar(Car):
def __init__(self, brand, colour, capacity):
super().__init__(brand, colour)
self.capacity = capacity
def introduce_yourself(self):
statement = f"My colour is {self.colour} and my capacity is {self.capacity} KG"
return statement
class SuperCargoCar(SuperCar):
"""you need not inherit from CargoCar as it has got only one extra
feature i.e. capacity which could be added to the new class directly
as inheriting this will lead to an absurd mro which will cause Python
to throw an exception"""
def __init__(self, brand, colour, max_speed, capacity):
SuperCar.__init__(self,brand, colour, max_speed)
self.capacity = capacity
#CargoCar.__init__(self,brand,colour,capacity)
def introduce_yourself(self):
statement = f'My colour is {self.colour}, my max speed is {self.max_speed} ' \
f'and my capacity is {self.capacity} KG'
return statement
super_cargo_car = SuperCargoCar(brand="Volvo", colour="Green", max_speed=200, capacity=5000)
print(super_cargo_car.introduce_yourself())
CodePudding user response:
As multiple inheritance in this case would create multiple of the same member (max_speed
and capacity
) which all kind of Car
has anyway I would suggest to refactor your code to something like this:
class Car:
def __init__(self, brand, colour, max_speed=None,capacity=None):
self.brand = brand
self.colour = colour
self.max_speed = max_speed
self.capacity = capacity
def introduce_yourself(self):
return f"I am a(n) {self.__class__.__name__} of {self.brand}." f" My colour is {self.colour}."
class SuperCar(Car):
def __init__(self, brand, colour, max_speed):
super().__init__(brand, colour, max_speed=max_speed)
def introduce_yourself(self):
return super().introduce_yourself() f" My max speed is {self.max_speed}."
class CargoCar(Car):
def __init__(self, brand, colour, capacity):
super().__init__(brand, colour,capacity=capacity)
def introduce_yourself(self):
return super().introduce_yourself() f" My capacity is {self.capacity} kg."
class SuperCargoCar(Car):
def __init__(self, brand, colour, max_speed, capacity ):
super().__init__(brand, colour,max_speed=max_speed,capacity=capacity)
def introduce_yourself(self):
return super().introduce_yourself() f" My max speed is {self.max_speed} and my capacity is {self.capacity} kg."
class Factory:
def __init__(self, brand):
self.brand = brand
def manufacture(self, colour, **kwargs):
kwargs['colour'] = colour
kwargs['brand'] = self.brand
if all(k in kwargs for k in ['max_speed','capacity']):
return SuperCargoCar(**kwargs)
if all(k in kwargs for k in ['max_speed']):
return SuperCar(**kwargs)
if all(k in kwargs for k in ['capacity']):
return CargoCar(**kwargs)
return Car(**kwargs)
factory = Factory(brand='Volvo')
car = factory.manufacture(colour="green", max_speed=200, capacity=5000)
print(car.introduce_yourself())
Each derived car will inherit all members and methods of the Car
class and only set the values which are specific to that type of car. I also introduced a Factory
class that will decide based on the arguments which derived Car
to manufacture. I also moved the brand to the factory so that all cars made there will have the same brand, but this is really up to you how you want to deal with that, I just showed some additional things you could make with this kind of structure.