How to Use itertools.accumulate in Python
Python's itertools.accumulate() function is a powerful,
memory-efficient tool designed to calculate running totals and
intermediate reductions over iterable data. While traditional reduction
tools like functools.reduce() return only the final
accumulated value, accumulate() returns an iterator
yielding every progressive step in the calculation. This article
explains how itertools.accumulate() operates under the
hood, how to implement basic running sums, and how to supply custom
binary functions to compute cumulative products, running maximums, and
specialized stateful reductions.
Syntax and Basic Operation
The function is imported from the standard library's
itertools module. Its basic signature is:
itertools.accumulate(iterable[, func, *, initial=None])By default, if no custom function is provided,
accumulate() uses standard addition (+). It
reads the first item from the input iterable, yields it, and then
continuously adds subsequent items to the running total, yielding each
intermediate result.
import itertools
numbers = [1, 2, 3, 4, 5]
running_sums = list(itertools.accumulate(numbers))
print(running_sums)
# Output: [1, 3, 6, 10, 15]Because accumulate() returns an iterator, it computes
values lazily. This ensures \(O(1)\)
auxiliary memory overhead, making it well-suited for processing massive
datasets or infinite streams.
Applying Custom Reductions
The func parameter allows you to replace default
addition with any callable that accepts two arguments: the current
accumulated value and the next item from the iterable.
1. Running Product
To calculate a running product (cumulative factorial or compounding
growth), pass operator.mul:
import itertools
import operator
numbers = [1, 2, 3, 4, 5]
running_product = list(itertools.accumulate(numbers, operator.mul))
print(running_product)
# Output: [1, 2, 6, 24, 120]2. Running Minimum or Maximum
You can track the progressive extreme values across an iterable by
passing Python’s built-in min or max
functions:
import itertools
temperatures = [72, 75, 71, 78, 69, 80]
running_max = list(itertools.accumulate(temperatures, max))
print(running_max)
# Output: [72, 75, 75, 78, 78, 80]3. Custom Logic Using Callables
Custom lambda functions or defined functions can implement domain-specific logic, such as compound interest or a bounded counter:
import itertools
# Simulate bank balance with a fixed 10% interest added to each deposit
deposits = [100, 200, 50]
compound = list(itertools.accumulate(deposits, lambda bal, dep: (bal * 1.10) + dep))
print(compound)
# Output: [100, 310.0, 391.0]Using the initial
Parameter
Python 3.8 introduced the initial keyword argument. When
provided, the iteration begins by yielding the initial
value, which is then used as the starting accumulation state for the
first element of the input iterable.
import itertools
data = [10, 20, 30]
# Start accumulation from a base value of 100
result = list(itertools.accumulate(data, initial=100))
print(result)
# Output: [100, 110, 130, 160]If the input iterable is empty and initial is specified,
accumulate() yields only the initial value. If
initial is not set and the input iterable is empty, it
returns an empty iterator.