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

Мини-проект: склад

Класс Stock ведёт остатки «Кофейной лавки» как встроенный контейнер: len, in, цикл по позициям, stock["Молоко"] и сложение поставок плюсом.

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

На складе «Кофейной лавки» — зёрна, молоко, сиропы и стаканы. Утром приходит поставка, днём бариста расходует запасы, вечером управляющий смотрит, чего осталось мало. Сделаем класс Stock, с которым всё это пишется так же коротко, как со словарём: len(stock), "Сироп" in stock, stock["Молоко"], for name in stock, а поставка добавляется оператором +.

Шаг 1. Склад-контейнер

[ ]Упражнение 1Класс Stock решено

Допишите класс Stock. Stock({"Зёрна": 8, "Молоко": 12}) хранит копию словаря «позиция → количество» во внутреннем атрибуте _items.

  • len(stock) — число позиций, у которых количество больше нуля;
  • stock["Молоко"] — количество позиции; если позиции нет — 0 (склад не ругается, а говорит «ноль»);
  • "Молоко" in stock — True, если позиция есть и её количество больше нуля;
  • for name in stock — названия позиций с количеством больше нуля, по алфавиту.
class Stock:
    def __init__(self, items):
        ...

    def __len__(self):
        ...

    def __getitem__(self, name):
        ...

    def __contains__(self, name):
        ...

    def __iter__(self):
        ...

Шаг 2. Поставка и расход

[ ]Упражнение 2Сложение и списание решено

Добавьте в класс (скопируйте его из шага 1 целиком):

  • __add__: stock + supply — новый склад, где количества одинаковых позиций сложены; оба слагаемых не меняются; сложение с чужим типом — NotImplemented;
  • метод take(name, amount) — списать amount единиц позиции; если на складе меньше — ValueError("на складе мало: <название>"), и ничего не меняется.
class Stock:
    # скопируйте сюда методы из шага 1

    def __add__(self, other):
        ...

    def take(self, name, amount):
        ...

Шаг 3. Утро

[ ]Упражнение 3Поставка пришла решено

На складе с вечера — leftover, утром пришла поставка delivery. Сохраните в stock склад после поставки, в n_positions — сколько на нём позиций, а в milk — сколько молока.

leftover = Stock({"Зёрна": 3, "Молоко": 2, "Сироп": 1, "Стаканы": 40, "Сливки": 0})
delivery = Stock({"Зёрна": 5, "Молоко": 10, "Сироп": 2, "Стаканы": 100})
stock = ...
n_positions = ...
milk = ...

Шаг 4. День

[ ]Упражнение 4Расход за день решено

В заготовке склад stock — такой, каким он стал утром после поставки (если выполнить ячейку ещё раз, он создастся заново). В usage — что бариста взяли со склада за день, по порядку. Спишите всё по очереди методом take; списания, на которые не хватило запасов, пропускайте, а их названия сохраните в short — в порядке попыток.

stock = Stock({"Зёрна": 8, "Молоко": 12, "Сироп": 3, "Стаканы": 140, "Сливки": 0})  # склад утром, после поставки
usage = [
    ("Молоко", 5), ("Стаканы", 60), ("Сироп", 2), ("Зёрна", 3),
    ("Стаканы", 78), ("Сироп", 2), ("Молоко", 4), ("Сироп", 1),
]
short = ...

Шаг 5. Вечерний отчёт

[ ]Упражнение 5Что заказать решено

Сохраните в low названия позиций, которых осталось меньше 5, — в порядке обхода склада циклом, а в out_of_syrup — True, если сиропа на складе не осталось.

low = ...
out_of_syrup = ...

Итог

[ ]Склад вечером
print(f"позиций: {len(stock)}")
for name in stock:
    mark = " ← заказать" if name in low else ""
    print(f"{name}: {stock[name]}{mark}")
print("не хватило:", ", ".join(short), "| сироп закончился:", out_of_syrup)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
позиций: 3
Зёрна: 5
Молоко: 3 ← заказать
Стаканы: 2 ← заказать
не хватило: Сироп | сироп закончился: True
Итог появится, когда решите все упражнения урока, — в нём ответы. Ячейку можно и выполнить.

Утренняя поставка закрыла почти всё, но сиропа хватило ненадолго: 3 бутылки к вечеру ушли полностью, и одно списание не прошло. Мало осталось молока и стаканов — их стоит заказать первыми.

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

Посмотрите на код шагов 3–5: в нём нет ни одного обращения к _items. Склад ведёт себя как встроенный контейнер, а как он хранит данные — его внутреннее дело. В последнем модуле перед итоговым проектом появятся dataclass — способ писать такие классы данных ещё короче.

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

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

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