What is the point of calling super from base(root) class in this multiple inheritance example?

40 views Asked by At

This is the code I am trying to run which is trying to calculate area of the right pyramid using the concept of multiple inheritance in Python

class Rectangle:
    def __init__(self, length, width, **kwargs):
        self.length = length
        self.width = width
        print("I am in Rectangle")
        print(kwargs)

        super().__init__(**kwargs)

    def area(self):
        return self.length * self.width

    def perimeter(self):
        return 2 * self.length + 2 * self.width

# Here we declare that the Square class inherits from
# the Rectangle class
class Square(Rectangle):
    def __init__(self, length, **kwargs):
        super().__init__(length=length, width=length, **kwargs)

        print("I am in Square")




class Cube(Square):
    def surface_area(self):
        face_area = super().area()
        return face_area * 6

    def volume(self):
        face_area = super().area()
        return face_area * self.length

class Triangle:
    def __init__(self, base, height, **kwargs):
        self.base = base
        self.height = height
        super().__init__(**kwargs)
        print("I am in Triangle")

    def tri_area(self):
        return 0.5 * self.base * self.height

class RightPyramid(Square, Triangle):
    def __init__(self, base, slant_height, **kwargs):
        self.base = base
        self.slant_height = slant_height
        kwargs["height"] = slant_height
        kwargs["length"] = base
        print(kwargs)
        super().__init__(base=base,**kwargs)

    def area(self):
        base_area = super().area()
        perimeter = super().perimeter()
        return 0.5 * perimeter * self.slant_height + base_area

    def area_2(self):
        base_area = super().area()
        triangle_area = super().tri_area()
        return triangle_area * 4 + base_area


Its fulfilling its purpose when I run it with this line of code

rrp = RightPyramid(2,2,height=3,length=4)
rrp.area_2()

Running the above gives 12 as the answer. But when I modify the Rectangle class to remove the super call:

class Rectangle:
    def __init__(self, length, width, **kwargs):
        self.length = length
        self.width = width
        print(f"I am in Rectangle")
        print(kwargs)

and then try to execute the area_2() function, it throws an error saying :

"AttributeError: 'RightPyramid' object has no attribute 'height'"

It seems triangle class was not initialized, but how is that possible? RightPyramid inherits from both square and triangle so the super call from RightPyramid should initialize both the classes irrespective of super being called from the root class. Why does it work fine when super call is added to the root class?

1

There are 1 answers

1
juanpa.arrivillaga On

It seems triangle class was not initialized, but how is that possible? RightPyramid inherits from both square and triangle so the super call from RightPyramid should initialize both the classes irrespective of super being called from the root class.

This is just not correct.

Here is the method resolution order (MRO) of RightPyramid:

In [2]: RightPyramid.mro()
Out[2]:
[__main__.RightPyramid,
 __main__.Square,
 __main__.Rectangle,
 __main__.Triangle,
 object]

As you can see, Rectangle is second to last in the MRO, so if it doesn't call super().__init__ then Triangle.__init__, the last class in the MRO, will never run.