Урок 005: функции и границы ответственности¶
Цель¶
Разделить программу на небольшие именованные операции: получение данных, проверку, расчёт и показ результата.
Объявление и вызов¶
def calculate_subtotal(unit_price, quantity):
return unit_price * quantity
subtotal = calculate_subtotal(125.50, 4)
print(f"Сумма: {subtotal:.2f} руб.")
defсоздаёт функцию.unit_priceиquantity— параметры.125.50и4— аргументы конкретного вызова.returnвозвращает результат вызывающему коду.
Функция не выполняется в момент объявления. Она выполняется при вызове calculate_subtotal(...).
return и print решают разные задачи¶
return передаёт значение другой части программы, поэтому его можно использовать в следующем расчёте или тесте. print показывает текст пользователю и обычно ничего полезного для вычисления не возвращает.
def calculate_discount(subtotal, discount_percent):
return subtotal * discount_percent / 100
subtotal = 500
discount = calculate_discount(subtotal, 10)
total = subtotal - discount
Расчёт не печатает сообщения и не запрашивает ввод. Благодаря этому одну функцию легко проверить несколькими наборами аргументов.
Функция чтения числа¶
def read_nonnegative_float(prompt):
while True:
text = input(prompt).replace(",", ".")
try:
value = float(text)
except ValueError:
print("Ошибка: введите число")
continue
if value < 0:
print("Ошибка: значение не может быть отрицательным")
continue
return value
return здесь одновременно возвращает корректное значение и завершает функцию. Пользовательский ввод и сообщение об ошибке находятся в одной функции, а математическая формула — в другой.
Полная минимальная программа¶
def calculate_total(unit_price, quantity, discount_percent):
subtotal = unit_price * quantity
discount = subtotal * discount_percent / 100
total = subtotal - discount
return subtotal, discount, total
subtotal, discount, total = calculate_total(100, 2, 10)
print(f"До скидки: {subtotal:.2f} руб.")
print(f"Скидка: {discount:.2f} руб.")
print(f"Итого: {total:.2f} руб.")
Функция возвращает три связанных результата. Для входа 100, 2, 10 ожидаются 200, 20, 180.
Признаки хорошей учебной функции¶
- имя описывает действие;
- параметры содержат все необходимые входные данные;
- функция выполняет одну понятную ответственность;
- расчёт не зависит от скрытого пользовательского ввода;
- результат возвращается через
return; - функцию можно вызвать повторно с другими аргументами.
Не разбивайте каждую строку в отдельную функцию. Граница полезна, когда часть программы имеет собственное правило, может быть переиспользована или отдельно проверена.
Упражнение¶
Создайте функции calculate_subtotal, calculate_discount и calculate_total. Проверьте их вручную на наборах (100, 2, 10), (100, 0, 10) и (99.90, 3, 0). Затем напишите отдельный блок, который печатает результаты.
Самопроверка¶
- Почему расчётная функция не должна вызывать
input? - Что произойдёт после выполнения
return? - Чем параметр отличается от аргумента?
- Как функция упрощает будущий автоматический тест?