Алгоритмы обработки данных

Фильтрация и накопление результата

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

Паттерн аккумулятора: сумма и произведение

Фильтрация возвращает список — подмножество исходного. Аккумулятор работает иначе: в конце получаем одно число, которое накапливалось по ходу перебора.

Начнём с чистого случая — сумма всех элементов без каких-либо условий:

def sum_all(numbers):
    total = 0
    for n in numbers:
        total += n
    return total

print(sum_all([3, -1, 7, -4, 2]))
# 7

total += n — сокращение от total = total + n. После каждой итерации total хранит промежуточный результат, и к концу цикла в нём оказывается итоговая сумма. Начальное значение 0 — нейтральный элемент сложения: 0 + x = x, поэтому первая итерация не искажает результат.

Для произведения структура та же, но начальное значение — 1, а оператор — *=:

def product_of(numbers):
    product = 1
    for n in numbers:
        product *= n
    return product

print(product_of([2, 3, 4]))
# 24

Почему именно 1? Потому что 1 — нейтральный элемент умножения: 1 * x = x. Если начать с 0, первое же умножение обнулит аккумулятор, и он останется нулём независимо от содержимого списка. Это одна из самых распространённых ошибок при переносе паттерна суммы на произведение:

# Неправильно — результат всегда 0
def broken_product(numbers):
    product = 0          # ← ошибка
    for n in numbers:
        product *= n
    return product

print(broken_product([2, 3, 4]))
# 0  — не то, что ожидалось

Запомнить легко: нулевая инициализация подходит только сложению. Для умножения — всегда 1.

Аккумулятор можно комбинировать с условием if внутри цикла — тогда накапливаются только подходящие элементы. Это расширение базового паттерна, а не его обязательная часть:

def sum_positive(numbers):
    total = 0
    for n in numbers:
        if n > 0:        # ← накапливаем только положительные
            total += n
    return total

print(sum_positive([3, -1, 7, -4, 2]))
# 12

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