F. Классный прямоугольник 2.0

Расширим функционал класса написанного вами в предыдущей задаче.

Реализуйте методы:

  • get_pos() — возвращает координаты верхнего левого угла в виде кортежа;
  • get_size() — возвращает размеры в виде кортежа;
  • move(dx, dy) — изменяет положение на заданные значения;
  • resize(width, height) — изменяет размер (положение верхнего левого угла остаётся неизменным).

Примечание

Ваше решение должно содержать только классы и функции.
В решении не должно быть вызовов инициализации требуемых классов.
Все результаты вычислений нужно округлить до сотых.

Пример

Ввод

rect = Rectangle((3.2, -4.3), (7.52, 3.14))
print(rect.get_pos(), rect.get_size())
rect.move(1.32, -5)
print(rect.get_pos(), rect.get_size())

Вывод

(3.2, 3.14) (4.32, 7.44)
(4.52, -1.86) (4.32, 7.44)

Ввод

rect = Rectangle((7.52, -4.3), (3.2, 3.14))
print(rect.get_pos(), rect.get_size())
rect.resize(23.5, 11.3)
print(rect.get_pos(), rect.get_size())

Вывод

(3.2, 3.14) (4.32, 7.44)
(3.2, 3.14) (23.5, 11.3)

Решение

Очень хорошее развитие предыдущей задачи. С одной стороны можно продолжать дорабатывать код из первой задачи, а с другой стороны можно заметить, Что нас подталкивают к тому, чтобы перейти от описания прямоугольника в виде пары координат к описанию “левый верхний угол, высота, ширина”.

На это указывает условие реализации метода resize(). Напомню, что там предлагают, чтобы левая верхняя точка оставалась в неизменном положении.

Это, в самом деле , более удобный подход, в чем можно будет убедиться в следующем задании.

И хотя мы могли бы использовать метод move() класса Point(), мы не будем этого делать, потому что в этом нет большого смысла. В классе Point() метод move() перемещает точку в новые координаты, а нам требуется ее сместить относительно текущего положения. Все это приводит к тому, что мы так или иначе будем вынуждены вычислить новые координаты, но вместо вызова метода move() точки из метода move() нашего прямоугольника, будет проще модифицировать координаты угла напрямую. При этом надо отдавать себе отчет, что это не является хорошей практикой в ООП.

Хорошей практикой ООП было бы использование методов, считывающих и устанавливающих координаты точки, но, с другой стороны, так как вызов функции – одна из самых дорогих операций в python, при больших объемах вычислений, этой практикой можно пренебречь.

Посмотреть код

Решение

Python
# продолжение первого, наивного решения

class Rectangle:
    def __init__(self, corner1, corner2) -> None:
        self.left_down = [min(corner1[0], corner2[0]),
                          min(corner1[1], corner2[1])]
        self.up_right = [max(corner1[0], corner2[0]),
                         max(corner1[1], corner2[1])]

    def perimeter(self):
        return round((self.up_right[0] - self.left_down[0]) * 2 +
                     (self.up_right[1] - self.left_down[1]) * 2, 2)

    def area(self):
        return round((self.up_right[0] - self.left_down[0]) *
                     (self.up_right[1] - self.left_down[1]), 2)

    def get_pos(self):
        return round(self.left_down[0], 2), round(self.up_right[1], 2)

    def get_size(self):
        return round(self.up_right[0] - self.left_down[0], 2), \
            round(self.up_right[1] - self.left_down[1], 2)

    def move(self, dx, dy):
        self.left_down[0] += dx
        self.left_down[1] += dy
        self.up_right[0] += dx
        self.up_right[1] += dy

    def resize(self, width, height):
        self.up_right[0] = self.left_down[0] + width
        self.left_down[1] = self.up_right[1] - height

Решение

Python
# решение на основе класса Point

class Point:
    def __init__(self, x, y) -> None:
        self.x = x
        self.y = y

    def round(self):
        self.x = round(self.x, 2)
        self.y = round(self.y, 2)
        return self


class Rectangle:
    def __init__(self, corner1, corner2) -> None:
        self.corner = Point(min(corner1[0], corner2[0]), max(corner1[1], corner2[1]))  # noqa
        self.width = round(max(corner1[0], corner2[0]) - self.corner.x, 2)
        self.height = round(self.corner.y - min(corner1[1], corner2[1]), 2)

    def perimeter(self):
        return round((self.width + self.height) * 2, 2)

    def area(self):
        return round(self.width * self.height, 2)

    def get_pos(self):
        return self.corner.x, self.corner.y

    def get_size(self):
        return self.width, self.height

    def move(self, dx, dy):
        self.corner.x += dx
        self.corner.y += dy
        self.corner.round()

    def resize(self, width, height):
        self.width = round(width, 2)
        self.height = round(height, 2)
Подписаться
Уведомить о
guest
7 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии