reduce() in Python combines the items of an iterable into a single value by applying a two-argument function over and over: first to items one and two, then to that result and item three, and so on. It lives in functools:
from functools import reduce
import operator
reduce(operator.add, [5, 10, 15]) # ((5 + 10) + 15) = 30
I printed the intermediate steps so you can watch reduce() work; the screenshots come from Python 3.12.5 in a Windows Command Prompt.
You’ll see exactly how it steps through a list, the initializer and the empty-list error, practical uses like merging and pipelines, and when a built-in or a loop beats it.
How reduce() works, step by step
The function you pass gets two arguments: the running result so far, and the next item. Printing inside it shows every step:
from functools import reduce
def add(total, amount):
print(f" {total:>8} + {amount:>7} = {total + amount}")
return total + amount
sales = [1240.50, 860.00, 1530.00, 410.25]
print("result:", reduce(add, sales))
Output:
1240.5 + 860.0 = 2100.5
2100.5 + 1530.0 = 3630.5
3630.5 + 410.25 = 4040.75
result: 4040.75

reduce() returns.Four sales took three calls. The first call uses the first two items, and every later call combines the previous result with one new item.
The initializer and ‘reduce() of empty iterable with no initial value’
An optional third argument gives reduce() a starting value. It’s also what saves you when the list is empty:
from functools import reduce
import operator
print(reduce(operator.add, [5, 10, 15])) # 30
print(reduce(operator.add, [5, 10, 15], 100)) # starts from 100: 130
print(reduce(operator.add, [], 0)) # empty, with an initializer: 0
try:
reduce(operator.add, []) # empty, no initializer
except TypeError as err:
print("TypeError:", err)
Output:
30
130
0
TypeError: reduce() of empty iterable with no initial value

reduce() raises TypeError.If there’s any chance the list could be empty, pass an initializer: 0 for addition, 1 for multiplication, an empty dict or list for merging.
Should you use reduce() or sum(), max() and math.prod()?
For the common cases, you’ll find a built-in that’s shorter, faster and easier to read. reduce() can do all of them, but you don’t need it to:
from functools import reduce
import math
import operator
nums = [4, 9, 2, 7]
print("product, reduce :", reduce(operator.mul, nums, 1))
print("product, prod :", math.prod(nums))
print("largest, reduce :", reduce(lambda a, b: a if a > b else b, nums))
print("largest, max :", max(nums))
print("total, reduce :", reduce(operator.add, nums))
print("total, sum :", sum(nums))
Output:
product, reduce : 504
product, prod : 504
largest, reduce : 9
largest, max : 9
total, reduce : 22
total, sum : 22
Use sum(), max(), min(), math.prod(), any() or all() when one fits. Python 3 moved reduce() out of the built-ins and into functools partly for this reason; an explicit loop is often clearer.
Merging dictionaries and counters with reduce()
Where reduce() earns its place is combining a list of things that don’t have a built-in shortcut, like inventory counts from several stores:
from functools import reduce
from collections import Counter
austin = Counter({"mugs": 14, "pens": 120})
dallas = Counter({"mugs": 6, "notebooks": 37})
houston = Counter({"pens": 80, "notebooks": 12})
total_stock = reduce(lambda a, b: a + b, [austin, dallas, houston])
print(dict(total_stock))
settings = [{"region": "us-east"}, {"retries": 3}, {"region": "us-west"}]
print(reduce(lambda a, b: a | b, settings)) # later dicts win (Python 3.9+)
Output:
{'mugs': 20, 'pens': 200, 'notebooks': 49}
{'region': 'us-west', 'retries': 3}
Counter objects add key by key, so three stores become one stock count. The | operator merges dictionaries, with later values winning, which is how the region ends up as us-west.
Using reduce() to apply a pipeline of functions
With an initializer, reduce() can pass a value through a list of functions in order. Here a $49.99 item gets 10% off, then Austin’s 8.25% sales tax, then rounding:
from functools import reduce
def discount(price):
return price * 0.90 # 10% off
def add_tax(price):
return price * 1.0825 # 8.25% Austin sales tax
def to_cents(price):
return round(price, 2)
steps = [discount, add_tax, to_cents]
price = 49.99
final = reduce(lambda value, step: step(value), steps, price)
print(f"${price:.2f} -> ${final:.2f}")
Output:
$49.99 -> $48.70

Adding a step is just adding a function to the list. I like this shape for price rules and data-cleaning steps that change over time.
reduce() vs itertools.accumulate()
reduce() only returns the final value. If you want every intermediate result, such as a running balance, use itertools.accumulate(), which takes the same kind of function:
from itertools import accumulate
from functools import reduce
import operator
deposits = [150, 150, 200, 150]
print("reduce :", reduce(operator.add, deposits)) # just the final total
print("accumulate :", list(accumulate(deposits))) # every running total
print("max so far :", list(accumulate([3, 7, 2, 9, 4], max)))
Output:
reduce : 650
accumulate : [150, 300, 500, 650]
max so far : [3, 7, 7, 9, 9]

reduce(), every running total from accumulate().Using reduce() with lambda vs the operator module
Most examples you’ll find pass a lambda, like lambda a, b: a + b. The operator module has ready-made versions, operator.add and operator.mul, which are a little faster and read better. Lambda functions in Python covers lambdas themselves.
reduce() often travels with map() and filter(): transform, keep, then combine. The map() function in Python covers the first step.
When to use reduce() in Python
| Goal | Best choice |
|---|---|
| Total | sum(items) |
| Product | math.prod(items) |
| Largest or smallest | max() / min() |
| Any or all true | any() / all() |
| Running totals | itertools.accumulate() |
| Merge many dicts or Counters | reduce() with | or + |
| Apply functions in order | reduce(lambda v, f: f(v), steps, start) |
| Anything with several steps per item | A plain for loop |
Related functional-programming tools in Python:
- The map() function in Python
- Lambda functions in Python
- The sum() function in Python
- Python list comprehension
- Python for loop
Frequently asked questions
What does reduce() do in Python?
It applies a two-argument function cumulatively to the items of an iterable, reducing them to a single value, such as a total or a merged dictionary.
Where is reduce() in Python 3?
In the functools module: from functools import reduce. It was a built-in in Python 2.
How do I fix ‘reduce() of empty iterable with no initial value’?
Pass an initializer as the third argument, such as reduce(operator.add, items, 0), so there’s a value to return when the iterable is empty.
What is the difference between reduce() and accumulate()?
reduce() returns only the final result. itertools.accumulate() returns every intermediate result as well.
Is reduce() faster than a for loop?
Not meaningfully. Use whichever reads better; for sums, products and maximums, the built-ins beat both.
Can I use reduce() with a lambda?
Yes, the function can be any callable that takes two arguments. The functools.reduce() documentation shows the exact signature.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn