← Назад к вопросам

Для чего нужен reduce?

1.3 Junior🔥 101 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Функция reduce: назначение, применение и практика

reduce — это мощный функциональный инструмент, который агрегирует последовательность значений в одно единственное значение. За 10+ лет разработки я вижу, что многие разработчики либо переусложняют его применение, либо не используют вообще, хотя он решает целый класс задач элегантно.

Определение и суть

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

from functools import reduce

reduce(function, sequence[, initial])

Алгоритм:

  1. Применяет функцию к первым двум элементам (или initial и первому)
  2. Применяет её к результату и следующему элементу
  3. Повторяет до конца последовательности

Классические применения

Суммирование элементов

Наиболее интуитивный пример:

from functools import reduce

numbers = [1, 2, 3, 4, 5]

# Старый способ (явный цикл)
total = 0
for n in numbers:
    total += n
print(total)  # 15

# Способ с reduce (декларативный)
result = reduce(lambda acc, x: acc + x, numbers)
print(result)  # 15

# Или с начальным значением
result = reduce(lambda acc, x: acc + x, numbers, 0)
print(result)  # 15

Нахождение произведения

from functools import reduce
import operator

numbers = [2, 3, 4, 5]

# Произведение всех чисел
product = reduce(operator.mul, numbers)
print(product)  # 120

# Или с lambda
product = reduce(lambda acc, x: acc * x, numbers, 1)
print(product)  # 120

Максимум/минимум (не совсем типичное использование, но возможно)

from functools import reduce

numbers = [5, 2, 8, 1, 9]

max_val = reduce(lambda acc, x: acc if acc > x else x, numbers)
print(max_val)  # 9

# Но для этого лучше использовать встроенные max()/min()
max_val = max(numbers)  # Яснее и быстрее

Продвинутые применения

Агрегирование данных в словарь

Это где reduce действительно сияет:

from functools import reduce

students = [
    {"name": "Alice", "grade": 5},
    {"name": "Bob", "grade": 4},
    {"name": "Charlie", "grade": 5},
    {"name": "Diana", "grade": 3},
]

# Подсчитаем студентов по оценкам
grade_counts = reduce(
    lambda acc, student: {
        **acc,
        student["grade"]: acc.get(student["grade"], 0) + 1
    },
    students,
    {}
)
print(grade_counts)  # {5: 2, 4: 1, 3: 1}

Вложенное агрегирование (группировка)

from functools import reduce

transactions = [
    {"user": "alice", "amount": 100},
    {"user": "bob", "amount": 50},
    {"user": "alice", "amount": 75},
    {"user": "bob", "amount": 25},
]

# Сумма по пользователям
user_totals = reduce(
    lambda acc, tx: {
        **acc,
        tx["user"]: acc.get(tx["user"], 0) + tx["amount"]
    },
    transactions,
    {}
)
print(user_totals)  # {"alice": 175, "bob": 75}

Композиция функций

Это более функциональный подход:

from functools import reduce

def compose(*functions):
    """Композиция функций слева направо"""
    return reduce(
        lambda f, g: lambda x: g(f(x)),
        functions,
        lambda x: x
    )

# Примеры функций
add_five = lambda x: x + 5
multiply_by_two = lambda x: x * 2
square = lambda x: x ** 2

# Композиция: (((x + 5) * 2) ^ 2)
pipeline = compose(add_five, multiply_by_two, square)
result = pipeline(3)  # ((3 + 5) * 2) ^ 2 = (8 * 2) ^ 2 = 16 ^ 2 = 256
print(result)  # 256

Складывание списка в одноуровневый список (flatten)

from functools import reduce

nested = [[1, 2], [3, 4], [5, 6]]

flattened = reduce(lambda acc, x: acc + x, nested, [])
print(flattened)  # [1, 2, 3, 4, 5, 6]

# Или более производительно с extend
flattened = reduce(
    lambda acc, x: (acc.extend(x) or acc),
    nested,
    []
)

Когда использовать reduce

✅ Хорошо подходит:

  • Агрегирование данных (суммы, произведения, подсчёты)
  • Создание словарей/объектов из последовательностей
  • Функциональное программирование и композиция
  • Компактный код для понятных операций

❌ Избегайте:

  • Если можно использовать встроенные функции (sum(), max(), min())
  • Для сложной логики (используйте цикл — он понятнее)
  • Если нужно обрабатывать ошибки (try-except внутри reduce — кошмар)
# Плохо: sum(numbers) куда проще
result = reduce(lambda x, y: x + y, [1, 2, 3])

# Хорошо: когда встроенного нет
result = reduce(lambda acc, x: acc | {x: len(x)}, words, {})

Альтернативы в Python

Частая рекомендация Гвидо ван Россума — использовать более явный и Pythonic код:

# Вместо reduce для сумм
total = sum(numbers)

# Вместо reduce для подсчётов
from collections import Counter
counts = Counter(grades)

# Вместо reduce для агрегирования
import pandas as pd
df = pd.DataFrame(transactions)
user_totals = df.groupby("user")["amount"].sum().to_dict()

Заключение

reduce — это инструмент для функционального программирования. Он полезен для:

  • Агрегирования — когда нужно свести много значений в одно
  • Функциональной композиции — когда пишете в стиле FP
  • Компактного кода — когда логика проста и понятна

Но помните: Python не язык функционального программирования. Если reduce делает код менее понятным — используйте цикл или специализированные функции (sum, groupby, pandas). Читаемость — первый критерий.