Part 8

Еще примеры классов

Пример 1: класс Rectangle

Посмотрим на класс, который моделирует прямоугольник в двумерном пространстве:

class Rectangle:
    def __init__(self, left_upper: tuple, right_lower: tuple):
        self.left_upper = left_upper
        self.right_lower = right_lower
        self.width = right_lower[0]-left_upper[0]
        self.height = right_lower[1]-left_upper[1]

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

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

    def move(self, x_change: int, y_change: int):
        corner = self.left_upper
        self.left_upper = (corner[0]+x_change, corner[1]+y_change)
        corner = self.right_lower
        self.right_lower = (corner[0]+x_change, corner[1]+y_change)

Новый объект Rectangle создается с двумя кортежами в качестве аргументов. Эти кортежи содержат координаты x и y верхнего левого угла и нижнего правого угла. Конструктор вычисляет высоту и ширину прямоугольника на основе этих значений.

Методы area и perimeter вычисляют площадь и периметр прямоугольника на основе высоты и ширины. Метод move перемещает прямоугольник на значения x и y, переданные как аргументы.

Прямоугольник представлен в системе координат, где координаты x увеличиваются слева направо, а координаты y — сверху вниз. Это распространенный способ работы с координатами в программировании, потому что часто проще и естественнее считать левый верхний угол экрана компьютера точкой, где x и y равны нулю.

Следующая программа тестирует класс Rectangle:

rectangle = Rectangle((1, 1), (4, 3))
print(rectangle.left_upper)
print(rectangle.right_lower)
print(rectangle.width)
print(rectangle.height)
print(rectangle.perimeter())
print(rectangle.area())

rectangle.move(3, 3)
print(rectangle.left_upper)
print(rectangle.right_lower)
Пример вывода

(1, 1) (4, 3) 3 2 10 6 (4, 4) (7, 6)

Печать объекта

Когда у вас есть объект, созданный из класса, который вы определили сами, стандартная реакция на вызов команды print с этим объектом в качестве аргумента не очень информативна:

rectangle = Rectangle((1, 1), (4, 3))
print(rectangle)

Вывод должен выглядеть примерно так:

Пример вывода

<main.Rectangle object at 0x000002D7BF148A90>

Очевидно, нам нужно больше контроля над тем, что выводится. Самый простой способ сделать это — добавить специальный метод __str__ в определение класса. Его задача — вернуть снимок состояния объекта в строковом формате. Если определение класса содержит метод __str__, при выполнении команды print будет выведено значение, возвращенное этим методом.

Итак, добавим определение метода __str__ в наш класс Rectangle:

class Rectangle:

    # ...the rest of the class goes here the same as above...

    # This method returns the state of the object in string format
    def __str__(self):
        return f"rectangle {self.left_upper} ... {self.right_lower}"

Теперь команда print выводит что-то более удобное для пользователя:

rectangle = Rectangle((1, 1), (4, 3))
print(rectangle)
Пример вывода

rectangle (1, 1) ... (4, 3)

Метод __str__, пожалуй, чаще используется для формирования строкового представления объекта с помощью функции str, как показано в следующей программе:

rectangle = Rectangle((1, 1), (4, 3))
str_rep = str(rectangle)
print(str_rep)
Пример вывода

rectangle (1, 1) ... (4, 3)

Есть еще много специальных методов с подчеркиваниями, которые можно определять для классов. Один из методов, довольно похожий на __str__, — это метод __repr__. Его задача — предоставить техническое представление состояния объекта. Мы встретимся с этим методом позже.

Loading
Loading
Loading

Пример 2: список задач

Следующий класс TaskList моделирует список задач:

class TaskList:
    def __init__(self):
        self.tasks = []

    def add_task(self, name: str, priority: int):
        self.tasks.append((priority, name))

    def get_next(self):
        self.tasks.sort()
        # The list method pop removes and returns the last item in a list
        task = self.tasks.pop()
        # Return the name of the task (the second item in the tuple)
        return task[1]

    def number_of_tasks(self):
        return len(self.tasks)

    def clear_tasks(self):
        self.tasks = []

Метод add_task добавляет новую задачу в список. У каждой задачи также есть связанный с ней приоритет, который используется для сортировки задач. Метод get_next удаляет и возвращает задачу с самым высоким приоритетом в списке. Также есть метод number_of_tasks, который возвращает количество задач в списке, и, наконец, метод clear_tasks, который очищает список задач.

Внутри объекта задачи хранятся в списке. Каждая задача представлена кортежем, содержащим приоритет задачи и ее имя. Значение приоритета хранится первым, поэтому при сортировке списка задача с самым высоким приоритетом оказывается последним элементом списка. Именно поэтому затем можно просто использовать метод pop, чтобы получить и удалить элемент с самым высоким приоритетом.

Посмотрите на следующую программу, где список задач используется на практике:

tasks = TaskList()
tasks.add_task("studying", 50)
tasks.add_task("exercise", 60)
tasks.add_task("cleaning", 10)
print(tasks.number_of_tasks())
print(tasks.get_next())
print(tasks.number_of_tasks())
tasks.add_task("date", 100)
print(tasks.number_of_tasks())
print(tasks.get_next())
print(tasks.get_next())
print(tasks.number_of_tasks())
tasks.clear_tasks()
print(tasks.number_of_tasks())
Пример вывода

3 exercise 2 3 date studying 1 0

Loading

Ответьте, пожалуйста, на короткую анкету по материалам этой недели.

Вы дошли до конца этого раздела!

Текущие баллы можно посмотреть в синем индикаторе в правом нижнем углу страницы.