Нашли ошибку?
Скачать чистый
мини-проект≈ 25 минупражнения: 0 из 5

Мини-проект: заказ с проверками

OrderLine и Order на dataclass, проверки в __post_init__, своя иерархия исключений, разбор строк заказа с raise … from и касса, которая перехватывает ошибки и пишет понятный отчёт.

Python запустится при первом выполнении

Заказы приходят в кассу «Кофейной лавки» строками вида "Латте;220;2" — название, цена, количество. Строки пишут люди, и в них бывают ошибки: отрицательная цена, буква вместо числа, пустой заказ. Касса не должна падать из-за одной плохой строки — она должна провести хорошие заказы и объяснить, что не так с остальными. В проекте собран весь модуль: dataclass, __post_init__, frozen=True, field(default_factory=list) и свои исключения.

Шаг 1. Ошибки заказа

[ ]Упражнение 1Иерархия исключений решено

Объявите ShopError — базовое исключение кассы (подкласс Exception) — и два его подкласса: InvalidLineError (строка заказа неверна) и EmptyOrderError (в заказе нет ни одной строки).

# объявите ShopError, InvalidLineError и EmptyOrderError

Шаг 2. Строка заказа

[ ]Упражнение 2OrderLine решено

Объявите неизменяемый dataclass OrderLine с полями product (строка), price (целое) и qty (целое, по умолчанию 1) и свойством cost — цена на количество. Если цена или количество не больше нуля, создание выбрасывает InvalidLineError с текстом "неверная строка: Чай, цена -120, количество 1".

from dataclasses import dataclass, field


class OrderLine:
    ...

Шаг 3. Заказ

[ ]Упражнение 3Order решено

Объявите dataclass Order с полями number (целое) и lines — список строк заказа, у каждого заказа свой, по умолчанию пустой. Метод add(line) добавляет строку, свойство total — сумма cost всех строк. Метод close() возвращает total, а если строк нет — выбрасывает EmptyOrderError("заказ №18 пуст") (с номером этого заказа).

class Order:
    ...

Шаг 4. Разбор строки

[ ]Упражнение 4Строка → OrderLine решено

Напишите функцию parse_line(text): из "Латте;220;2" она делает OrderLine("Латте", 220, 2). Если частей не три или цена и количество не разбираются в целые числа — InvalidLineError("не разобрать строку: <текст>"), а при ошибке int — с исходным ValueError в качестве причины (raise … from). Ошибки самой OrderLine (отрицательная цена) пусть уходят дальше как есть.

def parse_line(text):
    ...

Шаг 5. Касса за день

[ ]Упражнение 5Отчёт кассы решено

В словаре day — номера заказов и их строки. Для каждого заказа по порядку: создайте Order, разберите и добавьте строки, закройте заказ. Сохраните в results по строке на заказ: "№17: 580 ₽" для закрытого и "№18: ошибка — заказ №18 пуст" для заказа, на котором выброшено исключение кассы (текст — str исключения). Перехватывайте только ShopError — другие ошибки пусть видны.

day = {
    17: ["Латте;220;2", "Круассан;140;1"],
    18: [],
    19: ["Раф;260;1", "Чай;-120;1"],
    20: ["Какао;190;x2"],
    21: ["Эспрессо;150;3"],
}
results = ...

Итог

[ ]Касса за день
print("Касса за день")
for line in results:
    print(" ", line)
closed = [line for line in results if "ошибка" not in line]
print(f"проведено заказов: {len(closed)} из {len(results)}")
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
Касса за день
  №17: 580 ₽
  №18: ошибка — заказ №18 пуст
  №19: ошибка — неверная строка: Чай, цена -120, количество 1
  №20: ошибка — не разобрать строку: Какао;190;x2
  №21: 450 ₽
проведено заказов: 2 из 5
Итог появится, когда решите все упражнения урока, — в нём ответы. Ячейку можно и выполнить.

Из пяти заказов прошли два: №17 на 580 ₽ и №21 на 450 ₽. Остальные касса не провела, но объяснила почему: пустой заказ, отрицательная цена чая, буква в количестве какао. Ни одна ошибка не уронила кассу, а ошибки в самом коде — опечатки, неверные вызовы — except ShopError не спрятал бы.

Выводы с ответами появятся, когда решите все упражнения урока.

Иерархия исключений сделала отчёт простым: касса знает об одном классе ShopError и не перечисляет все виды ошибок. Новая проверка — скажем, «товара нет в меню» — это ещё один подкласс, и цикл дня не меняется. Остался итоговый проект: собрать всё, что было в курсе, в одну кассу.

Практика по модулю

Задачи по ООП в Python для самостоятельной практики появятся в разделе «Задачи → ООП в Python».

Нашли ошибку?