-1
class Car():    # Parent Class 1
    def __init__(self, brand, model, year):
        self.brand = brand
        self.model = model
        self.year = year
    def get_info(self):
        return "Car: " + self.model + "\nBrand: " + self.brand + "\nYear: " + self.year
    def get_fuel_info(self):
        return 'Class Car'

class Fuel_type():  # Parent Class 2
    def __init__(self, fuel):
        self.fuel = fuel
    def t(self):
        return "Class Fuel_Type"

class MyCar(Car, Fuel_type):    # Child Class derived from Car() & Fuel_type()
    def __init__(self, brand, model, year, fuel):
        super().__init__(brand, model, year)
        super().__init__(fuel)
        

car0 = MyCar('Tesla', 'Model S', '2016', 'Electric')

error:

Traceback (most recent call last):
  File "learning.py", line 23, in <module>
    car0 = MyCar('Tesla', 'Model S', '2016', 'Electric')
  File "learning.py", line 20, in __init__
    super().__init__(fuel)
TypeError: __init__() missing 2 required positional arguments: 'model' and 'year'

I don't know how to use the constructors of both the parent classes since how I am trying is giving me an error. Is there a way to get it right?

Although, if I comment out the line

super().__init__(brand, model, year)
super().__init__(fuel)

I can use all the functions of both the parent classes.

  • Note that inheritance implies an "is-a" relation – meaning ``MyCar`` "is-a" ``Car`` (okay), and ``MyCar`` "is-a" ``Fuel_type`` (?!?). Consider to use composition (``MyCar`` "has-a" ``Field_type``) instead of inheritance for this. – MisterMiyagi Jul 26 '20 at 09:07

4 Answers4

2

super works in Method Resolution Order (or mro). It's not designed for you to choose which parent class you'd like to call a method from.

You can find out what mro your class follows, by using .__mro__ on your class. The result of .__mro__ on MyCar is-

(__main__.MyCar, __main__.Car, __main__.Fuel_type, object)

As you can see, since the class directly after MyCar is Car, super() will actually choose that class.

If you'd like to choose a specific class's method, why not simply do ClassName.__init__(self)

class MyCar(Car, Fuel_type):    # Child Class derived from Car() & Fuel_type()
    def __init__(self, brand, model, year, fuel):
        super().__init__(brand, model, year)
        Fuel_type.__init__(self, fuel)
Chase
  • 5,315
  • 2
  • 15
  • 41
1

This is a classic multiple inheritance problem. There are multiple ways to solve your problem, the most simplest one specific to your code is shown below. Your init function should like either of below:

def __init__(self, brand, model, year, fuel):
    super().__init__(brand, model, year) # constructing car
    super(Car, self).__init__(fuel) # constructing Fuel_type 
   
def __init__(self, brand, model, year, fuel):
    Car.__init__(self, brand, model, year)
    Fuel_type.__init__(self, fuel)

Now the important thing is to understand the nuances of 'multiple inheritance' and use of 'super()' in python.There are many articles available online u can research them. I am posting 2 links that can be a good read. Suggest to read in the order posted.

  1. https://realpython.com/python-super/#an-overview-of-pythons-super-function
  2. https://rhettinger.wordpress.com/2011/05/26/super-considered-super/
AKHacks
  • 207
  • 1
  • 5
0

Super is only for the first extended class so super.__init__() is Car.__init__() if want fuel's __init__() use

Car.__init__(brand, model, year)
Fuel.__init__(fuel)
Dharman
  • 30,962
  • 25
  • 85
  • 135
12ksins
  • 307
  • 1
  • 12
-1

Wouldn't it better to have fuel as an attribute to MyCar, like this:

class MyCar(Car):
    def __init__(self, brand, model, year, fuel):
        super.__init__(brand, model, year)
        self.fuel = FuelType(fuel)

Also note that classnames usually are CamelCase, so you should skip the underscore in FuelType.

Torbjørn
  • 1
  • 2