Search code examples
pythonclasssubclass

How to assign a data attribute of a subclass to attributes of its parent class


I have a class Rectangle with data attributes width and height, I want a subclass Square with data attribute side_length.

How do I make it so that square.width and square.height give its side length? i.e same as square.side

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

class Square(Rectangle):
    def __init__(self, side)
        self.side = side

This is what I have so far.


Solution

  • You could call the constructor for Rectangle.

    super(Square,self).__init__(side, side)

    or you could have properties to return those attributes. I'd edge towards the super.

    @property
    def length(self):
       return self.side
    
    @property
    def width(self):
       return self.side
    

    Things get more complicated if you can change the side, height or width attribute after creating the object. You need to keep width and height synched and coherent. One possible way is to do away entirely with side as a stored attribute on Square and instead have it as a read-write property that updates Rectangle's width and height.

    to keep height/width/side sorted after the initial constructors:

    
    class Rectangle:
    
        @property
        def height(self):
            return self._height
    
        @height.setter
        def height(self, value):
            self._height = value
    
        @property
        def width(self):
            return self._width
    
        @width.setter
        def width(self, value):
            self._width = value
    
        def __repr__(self):
            return(f"{self.__class__.__name__}:{self.height=} {self.width=}")
    
        def __init__(self, height, width):
            self.height = height
            self.width = width
    
    class Square(Rectangle):
    
        def __repr__(self):
            return(f"{self.__class__.__name__}:{self.side=}")
    
        @property
        def side(self):
            return self._width
    
        @side.setter
        def side(self, value):
            self._width = value
            self._height = value
    
        def __init__(self, side):
            super(Square, self).__init__(side, side)
    
        #these are here so you can't cheat and vary height and width
        #independently on a square
        @property
        def width(self):
            return self.side
    
        @width.setter
        def width(self, value):
            self.side = value
    
        @property
        def height(self):
            return self._side
    
        @height.setter
        def height(self, value):
            self.side = value
    
    
    
    rectangle = Rectangle(5,2)
    print(rectangle)
    rectangle.height = 6
    print(rectangle)
    
    square = Square(3)
    print(square)
    square.side = 6
    print(square)
    square.height = 9
    print(square)
    

    output:

    $ py test_square.py
    Rectangle:self.height=5 self.width=2
    Rectangle:self.height=6 self.width=2
    Square:self.side=3
    Square:self.side=6
    Square:self.side=9