Confusion about inheritance in python OOP

Question:

class Shape():
  def __init__(self, name="unknown", sides=0, dimensions=0):
    self.sides = sides
    self.dimensions = dimensions
    self.name = name
    
  def desc(self):
    print("A", self.name, "has", self.sides, "sides and", self.dimensions, "dimensions")
    
class shape_2D(Shape):
  def __init__(self, name, sides, dimensions):
    super().__init__(name, sides, 2)
    
square = shape_2D(name="square", sides = 4, dimensions=2)
square.desc()

class shape_3D(shape_2D):
  def __init__(self, name, sides, dimensions):
    super().__init__(name, sides, 3)

cube = shape_3D(name="cube", sides = 6, dimensions = 3)
cube.desc()

running this program outputs "A square has 4 sides and 2 dimensions
A cube has 6 sides and 2 dimensions"

Why isn’t this outputting 3 dimensions for the cube class? Similarly, is there a way I can code this so I don’t need to add the dimensions when defining cube or square, I thought the whole point of using a class is that it will inherit the dimensions from that class so I wouldn’t need to define the number of dimensions. Also, apologies if this is terrible coding, I’m very new to this sort of thing!

Asked By: TeeEmDee

||

Answers:

When you are calling shape_3D to construct a new instance of the class, this will call shape_3D.__init__, which will call shape_2D.__init__, and this call overrides the dimension to 2.

To achieve what you want to do, you need make shape_3D inherit from Shape directly. This should make sense, because a 3D shape is particular type of shape, not 2d shape.

Hence, to achieve what you want here, you will need to do something like this:


class shape_2D(Shape):
  def __init__(self, name, sides):
    super().__init__(name, sides, dimensions=2)


class shape_3D(Shape):
  def __init__(self, name, sides):
    super().__init__(name, sides, dimensions=3)

Notice how I have remove the parameter dimensions from the constructor of shape_2D and shape_3D.

Then, you can create your objects as so:

>>> square = shape_2D(name="square", sides=4)
>>> square.desc()
A square has 4 sides and 2 dimensions
>>> cube = shape_3D(name="cube", sides=6)
>>> cube()
A cube has 6 sides and 3 dimensions.

As a side note, consider following the PEP8 naming conventions regarding class names.

Answered By: Florent Monin

Both of your shape_2d and shape_3d have dimension parameter to __init__ that is not used and instead you pass fixed value to super’s init. Since your shape_3d inherits from shape_2d for some reason, the 3 you pass is ignored and 2 is used in its place. Remove the pointless parameter and change the inheritance so it makes more sense:

class Shape():
    def __init__(self, name="unknown", sides=0, dimensions=0):
        self.sides = sides
        self.dimensions = dimensions
        self.name = name
        
    def desc(self):
        return f"A {self.name} has {self.sides} sides and {self.dimensions} dimensions"
    
class shape_2D(Shape):
    def __init__(self, name, sides):
        super().__init__(name, sides, 2)
    
square = shape_2D(name="square", sides = 4)
print(square.desc())

class shape_3D(Shape):
    def __init__(self, name, sides):
        super().__init__(name, sides, 3)

cube = shape_3D(name="cube", sides = 6)
print(cube.desc())
Answered By: matszwecja
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.