0

i have a Square that inherits from Rectangle which inherits from Base. I'm trying to overwrite the str method in Square class so it can return [Square] () / - , but it says that Square doesn't have the attributes __x, __y, __width and __height

Directory tree:

~/learning_programming/0x0C-python-almost_a_circle$ tree
.
├── 9-main.py
├── models
│   ├── base.py
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── base.cpython-39.pyc
│   │   ├── __init__.cpython-39.pyc
│   │   ├── rectangle.cpython-39.pyc
│   │   └── square.cpython-39.pyc
│   ├── rectangle.py
│   └── square.py

Classes: Base:

#!/usr/bin/python3
"""Base class for all other classes in this module"""


class Base:
    """Base Class

    Args:
        __nb_objects (int): number of instances of class
    """
    __nb_objects = 0

    def __init__(self, id=None):
        """class constructor

        Args:
            id (int, optional): argument value to initialize. Defaults to None.
        """
        if id is not None:
            self.id = id
        else:
            type(self).__nb_objects += 1
            self.id = type(self).__nb_objects

Rectangle:

#!/usr/bin/python3
"""Definition of Rectangle"""
from . base import Base


class Rectangle(Base):
    """define a rectangle object

    Args:
        Base (class): Base Class
    """

    def __init__(self, width, height, x=0, y=0, id=None):
        """rectangle constructor

        Args:
            width (int): width of rectangle
            height (int): height of rectangle
            x (int, optional): x offset of rectangle. Defaults to 0.
            y (int, optional): y offset of rectangle. Defaults to 0.
            id (int, optional): identifier. Defaults to None.
        """
        super().__init__(id)
        if type(width) is not int:
            raise TypeError('width must be an integer')
        if width <= 0:
            raise ValueError('width must be > 0')
        self.__width = width

        if type(height) is not int:
            raise TypeError('height must be an integer')
        if height <= 0:
            raise ValueError('height must be > 0')
        self.__height = height

        if type(x) is not int:
            raise TypeError('x must be an integer')
        if x < 0:
            raise ValueError('x must be >= 0')
        self.__x = x

        if type(y) is not int:
            raise TypeError('y must be an integer')
        if y < 0:
            raise ValueError('y must be >= 0')
        self.__y = y


    def area(self):
        """returns the area value of the Rectangle instance"""
        return self.__width * self.__height

    def display(self):
        """prints in stdout the Rectangle instance with the character #"""
        print(('\n' * self.__y) + '\n'
              .join(' ' * self.__x + '#' * self.__width
                    for _ in range(self.__height)))

    def __str__(self):
        """Returns an informal string representation a Rectangle object"""
        return '[Rectangle] ({}) {}/{} - {}/{}'\
            .format(self.id, self.__x, self.__y,
                    self.__width, self.__height)

    def update(self, *args, **kwargs):
        """update the instance attributes"""
        if len(kwargs):
            if 'height'in kwargs:
                self.__height = kwargs['height']
            if 'width'in kwargs:
                self.__width = kwargs['width']
            if 'x'in kwargs:
                self.__x = kwargs['x']
            if 'y'in kwargs:
                self.__y = kwargs['y']
            if 'id'in kwargs:
                self.id = kwargs['id']


        else:
            try:
                self.id = args[0]
                self.__width = args[1]
                self.__height = args[2]
                self.__x = args[3]
                self.__y = args[4]
            except IndexError:
                pass

Square:

#!/usr/bin/python3
"""Definition of Square Object"""
from . rectangle import Rectangle


class Square(Rectangle):
    """defines a Square object

    Args:
        Rectangle (class): Sub Class to inherit from
    """

    def __init__(self, size, x=0, y=0, id=None):
        """square constructor

        Args:
            size (int, optional): size of square
            x (int, optional): x offset of square. Defaults to 0.
            y (int, optional): y offset of square. Defaults to 0.
            id (int, optional): identifier . Defaults to None.
        """
        super().__init__(size, size, x, y, id)

    def __str__(self):
        """Returns an informal string representation a Square object"""
        return '[Square] ({}) {}/{} - {}'\
            .format(self.id, self.__x, self.__y,
                    self.__width)

when I run 9-main.py:

#!/usr/bin/python3
""" 9-main """
from models.square import Square

if __name__ == "__main__":

    s1 = Square(5)
    print(s1)
    print(s1.area())
    s1.display()

    print("---")

    s2 = Square(2, 2)
    print(s2)
    print(s2.area())
    s2.display()

    print("---")

    s3 = Square(3, 1, 3)
    print(s3)
    print(s3.area())
    s3.display()

I get the error:

Traceback (most recent call last):
  ...
  File "/home/marlon/learning_programming/0x0C-python-almost_a_circle/models/square.py", line 27, in __str__
    .format(self.id, self.__x, self.__y,
AttributeError: 'Square' object has no attribute '_Square__x

What am I doing wrong ?

Marlon
  • 55
  • 3
  • You can't access private attributes from child classes, only from the same class. Either make `x` and `y` normal attributes, or define getters. – Barmar May 09 '22 at 16:32
  • Any property with `__` in front of it will get its _current_ class name appended to the identifier, effectively making them private - so you can't access them from a child class. – MatsLindh May 09 '22 at 16:39

0 Answers0