Глава 13 · Автоматизация с помощью функций

Проектируем хорошую функцию

Прежде чем писать реализацию, полезно спроектировать функцию: одна ясная обязанность, понятное имя, чёткий контракт.

Хорошие имена — глаголы-действия

ХорошоПлохо
calculate_total()do_it()
normalize_text()func1()
draw_polygon()thing()
find_max_score()test2()

Функции обычно представляют ДЕЙСТВИЕ — имя должно быть глаголом или глагольной фразой. Для функций, возвращающих True/False, хорошо работают префиксы is_, has_, can_, contains_ — они прямо сообщают, что вернётся булево значение.

Одна функция — одна понятная обязанность

plohaya_dekompoziciya.py
def process_everything():
    # спрашивает ввод
    # проверяет
    # считает
    # печатает
    # рисует
    # обновляет пять структур данных
    ...
horoshaya_dekompoziciya.py
def read_answer(): ...
def normalize_answer(answer): ...
def check_answer(answer, correct): ...
def show_result(correct): ...
Это ориентир, а не догма
Небольшие программы вполне могут разумно объединять несколько простых действий в одной функции — не нужно дробить каждую строку в отдельную функцию искусственно (пример того, ЧЕГО не стоит делать, — в §13.19). Цель — ясность, а не количество функций.

Сколько строк должна занимать функция?

Не существует правила вида «максимум 10 строк». Вместо количества строк спрашивайте:

Вопросы вместо количества строк
1
Есть ли у неё одна ясная цель?
2
Объясняет ли имя, что она делает?
3
Легко ли её протестировать отдельно?
4
Есть ли внутри сильно повторяющаяся логика?
5
Понятны ли входы и выход читателю?

Контракт функции

Прежде чем писать реализацию, полезно явно сформулировать контракт — что функция принимает, что возвращает, и есть ли у неё побочные эффекты:

Часть контрактаcalculate_discount(price, percent)
Входprice: число, percent: число
Выходцена со скидкой
Побочные эффектынет
Примерcalculate_discount(100, 10) → 90

Предусловия

Некоторые функции ожидают осмысленный вход — например, draw_polygon(sides, length) предполагает sides >= 3 и length > 0. Это предусловия — требования к входным данным, которые стоит проверить обычными условиями:

predusloviya.py
def polygon_angle(sides):
    if sides < 3:
        return None

    return 360 / sides
None — не единственный вариант
Возврат None при неверном входе — простой и рабочий вариант на этом уровне курса. Более строгие способы (например, поднять исключение) рассматриваются в главах, посвящённых обработке ошибок.

Чек-лист проектирования функции

Прежде чем написать def

  • Какую ОДНУ работу она выполняет?
  • Какие данные ей нужны? Это и есть параметры.
  • Возвращает ли она результат — и какой?
  • Меняет ли она что-то намеренно (побочный эффект)?
  • Как её назвать, чтобы имя объясняло действие?
  • На каких входных данных её стоит проверить?
Практика: проектируем функцию по контракту
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки
Открыть практику →