Функции

Декомпозиция программы на функции

Содержание курса

Пошаговая процедура разбиения программы на функции

Теперь посмотрим, как всё это работает на практике — от монолитного кода до готового набора функций.

Возьмём конкретную программу: она запрашивает цену товара, применяет скидку 10% и печатает итоговую сумму. В исходном виде всё написано подряд, одним блоком:

price = float(input("Введите цену: "))
discounted = price * 0.9
print(f"Итого со скидкой: {discounted:.2f} руб.")

Пока три строки — всё читается. Но представьте, что таких расчётов пять, и каждый немного отличается. Вот тут начинается боль. Разберём декомпозицию по шагам.

Шаг 1. Найти логически самостоятельные блоки

Смотрим на код и задаём себе вопрос: что здесь происходит? Три отдельных действия:

  • получить цену от пользователя;
  • посчитать цену со скидкой;
  • показать результат.

Каждое из них — кандидат на отдельную функцию.

Шаг 2. Придумать говорящие имена

По одному глаголу на каждое действие: get_price, apply_discount, print_receipt. Если имя не придумывается без союза «и» — блок нужно делить дальше.

Шаг 3. Оформить каждый блок как функцию

Жёстко заданные значения (например, коэффициент скидки 0.9) выносим в параметры — так функция становится гибкой:

def get_price():
    return float(input("Введите цену: "))

def apply_discount(price, rate):
    return price * (1 - rate)

def print_receipt(price):
    print(f"Итого со скидкой: {price:.2f} руб.")

Обратите внимание: apply_discount не знает, откуда пришла цена и куда пойдёт результат. Она только считает. Именно это делает её универсальной.

Шаг 4. Заменить исходный код вызовами функций

price = get_price()
discounted = apply_discount(price, rate=0.1)
print_receipt(discounted)

Три строки остались тремя строками, но теперь каждая из них — осмысленное действие с именем, а не безымянное вычисление.

Шаг 5. Запустить программу и сравнить результат

Запускаем, вводим то же значение, что вводили раньше, и проверяем: вывод совпадает с исходным? Если да — рефакторинг прошёл чисто. Программа делает то же самое, просто теперь это видно по именам функций, а не по деталям арифметики.

Вот промежуточный результат — функции выделены, вызовы на верхнем уровне:

def get_price():
    return float(input("Введите цену: "))

def apply_discount(price, rate):
    return price * (1 - rate)

def print_receipt(price):
    print(f"Итого со скидкой: {price:.2f} руб.")

price = get_price()
discounted = apply_discount(price, rate=0.1)
print_receipt(discounted)

Если через месяц понадобится изменить ставку скидки или поменять формат вывода — вы точно знаете, в какой функции это сделать. И только в ней.

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

Начать заново?

Помощник начнёт новый диалог по этой задаче. Текущая переписка останется в истории до конца срока хранения.

О переписке

Можно приложить до трёх фото PNG, JPEG или WebP по 5 МБ.

Переписка и фото хранятся 90 дней после последнего принятого сообщения. Преподаватель получит доступ к диалогу, когда вы попросите его помочь.

Проверка решения остаётся отдельным действием.