Перейти к содержанию

Паттерны функционального программирования

Начало урока

Паттерны функционального программирования

Чистые функции, неизменяемость и композируемые конвейеры с functools и itertools

Главная идея: Функциональное программирование (ФП) — это стиль, а не отдельный язык. Вы строите программы из чистых функций, которые отображают входы в выходы без скрытых побочных эффектов, относитесь к данным как к неизменяемым и компонуете маленькие функции в конвейеры. Python не является чисто функциональным языком, но у него мощный набор инструментов ФП: функции как объекты первого класса, functools, itertools, включения и генераторы. При осознанном применении они дают код, который проще тестировать, кешировать и понимать — при бездумном применении получаются нечитаемые однострочники. Эта тема о применении ФП там, где оно окупается.
К концу вы сможете:
  • дать определение чистой функции и объяснить ссылочную прозрачность,
  • выбирать неизменяемые структуры (tuple, frozenset, замороженный dataclass) и избегать ошибок общего изменяемого состояния,
  • брать нужный инструмент из functools: reduce, partial, lru_cache, singledispatch,
  • лениво обрабатывать поток данных с itertools (chain, islice, groupby, accumulate, takewhile),
  • компоновать маленькие преобразования в читаемый конвейер,
  • честно признавать, когда ФП вредит читаемости в Python.

1. Чистые функции и ссылочная прозрачность

Функция чистая, когда выполняет два правила: (1) её возвращаемое значение зависит только от аргументов и (2) она не производит наблюдаемых побочных эффектов — не меняет внешнее состояние, не делает ввод-вывод, не читает часы или случайные числа. Одни и те же входы всегда дают один и тот же результат.

# ЧИСТАЯ: результат зависит только от входов, ничего внешнего не меняется
def add_tax(price: float, rate: float) -> float:
    return round(price * (1 + rate), 2)

# НЕЧИСТАЯ: читает глобальную, меняет глобальную и делает ввод-вывод
TOTAL = 0.0
def add_tax_bad(price: float) -> float:
    global TOTAL
    result = price * 1.2
    TOTAL += result          # побочный эффект: меняет внешнее состояние
    print(result)            # побочный эффект: ввод-вывод
    return result

Ссылочная прозрачность означает, что любой вызов чистой функции можно заменить его результатом, не меняя программу. add_tax(100, 0.2) везде взаимозаменяем со значением 120.0. Именно это свойство делает чистые функции тривиально тестируемыми (без фикстур и моков), безопасными для кеширования и безопасными для параллельного запуска — нет общего состояния, которое можно испортить.

Чистота — это спектр. Настоящая программа рано или поздно должна делать ввод-вывод. Практическая цель — чистое ядро (вычисления) с тонкой нечистой оболочкой (чтение файлов, вывод, запись в базу) по краям — это часто называют функциональное ядро, императивная оболочка.

Продолжите этот урок на YourAIZone

В полном уроке — объяснение целиком, разобранные примеры, частые ошибки, тесты с мгновенной проверкой и ИИ-репетитор. Начните сразу как гость или создайте аккаунт, чтобы сохранять прогресс.

В полном уроке

  • Объяснение целиком
  • Разобранные примеры
  • Частые ошибки и как их избежать
  • Тестовые вопросы: 15
  • ИИ-репетитор, который отвечает на вопросы по теме
  • Отслеживание прогресса для ученика, родителей и учителя