What is reduce()?
reduce() folds a list down to a single value by applying a function sequentially.
Without reduce() (the old way):
numbers = [1, 2, 3, 4, 5]
# Sum all numbers
total = 0
for num in numbers:
total = total + num
print(total) # 15
With reduce() (elegant!):
from functools import reduce
numbers = [1, 2, 3, 4, 5]
total = reduce(lambda acc, x: acc + x, numbers)
print(total) # 15
One line instead of a loop with an accumulator! 🚀
reduce() syntax
from functools import reduce
reduce(function, iterable, initial_value)
Parameters:
- function — takes 2 arguments: the accumulator and the current element
- iterable — a list, tuple, etc.
- initial_value — optional starting value for the accumulator
Returns: A single value (not a list!)
How does reduce() work?
Step-by-step visualization:
from functools import reduce
numbers = [1, 2, 3, 4, 5]
result = reduce(lambda acc, x: acc + x, numbers)
Step by step:
Step 1: acc=1, x=2 → 1 + 2 = 3
Step 2: acc=3, x=3 → 3 + 3 = 6
Step 3: acc=6, x=4 → 6 + 4 = 10
Step 4: acc=10, x=5 → 10 + 5 = 15
Result: 15
The accumulator (acc) is the variable that builds up the result!
Basic examples
1. Sum of numbers
from functools import reduce
numbers = [1, 2, 3, 4, 5]
total = reduce(lambda acc, x: acc + x, numbers)
print(total) # 15
# With an initial value
total = reduce(lambda acc, x: acc + x, numbers, 10)
print(total) # 25 (10 + 1 + 2 + 3 + 4 + 5)
2. Product of numbers
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda acc, x: acc * x, numbers)
print(product) # 120 (1 * 2 * 3 * 4 * 5 = factorial!)
# With initial value of 1
product = reduce(lambda acc, x: acc * x, numbers, 1)
print(product) # 120
3. Maximum value
numbers = [5, 12, 3, 18, 25, 7]
maximum = reduce(lambda acc, x: acc if acc > x else x, numbers)
print(maximum) # 25
4. Minimum value
numbers = [5, 12, 3, 18, 25, 7]
minimum = reduce(lambda acc, x: acc if acc < x else x, numbers)
print(minimum) # 3
reduce() with strings
String concatenation
words = ["Python", "is", "awesome"]
sentence = reduce(lambda acc, word: acc + " " + word, words)
print(sentence) # "Python is awesome"
# Better with an initial value
sentence = reduce(lambda acc, word: acc + " " + word, words, "")
print(sentence.strip()) # "Python is awesome" (leading space removed)
Joining with a separator
words = ["apple", "banana", "orange"]
# Comma-separated
result = reduce(lambda acc, word: f"{acc}, {word}", words)
print(result) # "apple, banana, orange"
# Or just use join! (simpler)
result = ", ".join(words)
print(result) # "apple, banana, orange"
reduce() with dictionaries
Summing values
sales = [
{"product": "Phone", "revenue": 500},
{"product": "Laptop", "revenue": 1200},
{"product": "Mouse", "revenue": 25}
]
total_revenue = reduce(lambda acc, sale: acc + sale["revenue"], sales, 0)
print(total_revenue) # 1725
Merging dictionaries
dicts = [
{"a": 1},
{"b": 2},
{"c": 3}
]
merged = reduce(lambda acc, d: {**acc, **d}, dicts, {})
print(merged) # {'a': 1, 'b': 2, 'c': 3}
Counting occurrences
items = ["apple", "banana", "apple", "orange", "banana", "apple"]
# Count each item
count = reduce(
lambda acc, item: {**acc, item: acc.get(item, 0) + 1},
items,
{}
)
print(count) # {'apple': 3, 'banana': 2, 'orange': 1}
The initial value (important!)
Without an initial value:
numbers = [1, 2, 3, 4, 5]
result = reduce(lambda acc, x: acc + x, numbers)
# acc starts as the first element (1)
print(result) # 15
With an initial value:
numbers = [1, 2, 3, 4, 5]
result = reduce(lambda acc, x: acc + x, numbers, 0)
# acc starts at 0
print(result) # 15
When is the initial value REQUIRED?
1. Empty list:
# WITHOUT initial value — ERROR!
result = reduce(lambda acc, x: acc + x, [])
# ❌ TypeError: reduce() of empty sequence with no initial value
# With initial value — OK
result = reduce(lambda acc, x: acc + x, [], 0)
print(result) # 0
2. When the result type differs from the element type:
numbers = [1, 2, 3, 4, 5]
# Building a dictionary from numbers
result = reduce(
lambda acc, x: {**acc, str(x): x ** 2},
numbers,
{} # ← REQUIRED! The result is a dict, not a number
)
print(result) # {'1': 1, '2': 4, '3': 9, '4': 16, '5': 25}
Practical examples
Example 1: Factorial
def factorial(n):
return reduce(lambda acc, x: acc * x, range(1, n + 1), 1)
print(factorial(5)) # 120 (1 * 2 * 3 * 4 * 5)
print(factorial(0)) # 1 (correct!)
Example 2: Flatten a nested list
nested = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
flattened = reduce(lambda acc, lst: acc + lst, nested, [])
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
Example 3: Function pipeline
def add_10(x):
return x + 10
def multiply_2(x):
return x * 2
def square(x):
return x ** 2
# Apply all functions in sequence
functions = [add_10, multiply_2, square]
result = reduce(lambda acc, func: func(acc), functions, 5)
# 5 → add_10 → 15 → multiply_2 → 30 → square → 900
print(result) # 900
Example 4: Find the longest element
words = ["cat", "elephant", "dog", "hippopotamus"]
longest = reduce(
lambda acc, word: word if len(word) > len(acc) else acc,
words
)
print(longest) # "hippopotamus"
reduce() vs sum() / max() / min()
For simple operations, use built-in functions!
numbers = [1, 2, 3, 4, 5]
# reduce
total = reduce(lambda acc, x: acc + x, numbers)
# sum (SIMPLER!)
total = sum(numbers)
print(total) # 15
When to use reduce():
- ✅ Complex logic (not just sum/max/min)
- ✅ Non-standard folding operations
- ✅ Function pipelines / transformations
When NOT to use reduce():
- ❌ Summing → use
sum() - ❌ Maximum → use
max() - ❌ Minimum → use
min() - ❌ Joining strings → use
"".join()
reduce() with a regular function
Lambdas are optional — you can use a named function:
def add(acc, x):
"""Addition function for reduce."""
print(f"acc={acc}, x={x}, result={acc + x}")
return acc + x
numbers = [1, 2, 3, 4, 5]
result = reduce(add, numbers)
# Output:
# acc=1, x=2, result=3
# acc=3, x=3, result=6
# acc=6, x=4, result=10
# acc=10, x=5, result=15
print(result) # 15
Useful for debugging!
Combining reduce + map + filter
Functional programming in action!
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Even numbers → double them → sum
result = reduce(
lambda acc, x: acc + x,
map(lambda x: x * 2, filter(lambda x: x % 2 == 0, numbers)),
0
)
print(result) # 60
# Step by step:
# filter: [2, 4, 6, 8, 10]
# map: [4, 8, 12, 16, 20]
# reduce: 4 + 8 + 12 + 16 + 20 = 60
Reads right to left!
Common mistakes
Mistake 1: Forgot to import
# ❌ ERROR
result = reduce(lambda acc, x: acc + x, [1, 2, 3])
# NameError: name 'reduce' is not defined
# ✅ CORRECT
from functools import reduce
result = reduce(lambda acc, x: acc + x, [1, 2, 3])
Mistake 2: Function doesn’t return a value
def add_bad(acc, x):
acc + x # Missing return!
result = reduce(add_bad, [1, 2, 3])
print(result) # None ← Bug!
# ✅ CORRECT
def add_good(acc, x):
return acc + x
result = reduce(add_good, [1, 2, 3])
print(result) # 6
Mistake 3: Empty list without an initial value
# ❌ ERROR
result = reduce(lambda acc, x: acc + x, [])
# TypeError: reduce() of empty sequence with no initial value
# ✅ CORRECT
result = reduce(lambda acc, x: acc + x, [], 0)
print(result) # 0
Mistake 4: Wrong argument order
# ❌ ERROR
result = reduce(lambda x, acc: acc + x, [1, 2, 3])
# Order matters! The first argument is the ACCUMULATOR
# ✅ CORRECT
result = reduce(lambda acc, x: acc + x, [1, 2, 3])
Alternatives to reduce()
Instead of reduce for summing:
numbers = [1, 2, 3, 4, 5]
# reduce
total = reduce(lambda acc, x: acc + x, numbers, 0)
# sum (BETTER!)
total = sum(numbers)
Instead of reduce for max:
numbers = [5, 12, 3, 18, 25]
# reduce
maximum = reduce(lambda acc, x: acc if acc > x else x, numbers)
# max (BETTER!)
maximum = max(numbers)
Instead of reduce for complex cases:
# reduce
result = reduce(lambda acc, x: {**acc, x: x ** 2}, [1, 2, 3], {})
# dict comprehension (BETTER!)
result = {x: x ** 2 for x in [1, 2, 3]}
Performance
reduce() is fast, but not always the fastest option!
import time
numbers = list(range(1000000))
# reduce
start = time.time()
result1 = reduce(lambda acc, x: acc + x, numbers, 0)
time_reduce = time.time() - start
# sum (built-in function)
start = time.time()
result2 = sum(numbers)
time_sum = time.time() - start
print(f"reduce: {time_reduce:.4f}s")
print(f"sum: {time_sum:.4f}s")
# sum is typically 2–3x faster!
Built-in functions are optimized in C!
Summary
reduce() is:
- ✅ Folding a list into a single value
- ✅ Uses an accumulator
- ✅ Applies a function sequentially
- ✅ Function takes (accumulator, element)
- ✅ Must be imported:
from functools import reduce
Syntax:
from functools import reduce
reduce(lambda acc, x: ..., data, initial_value)
Typical usage:
# Sum
reduce(lambda acc, x: acc + x, numbers, 0)
# Product
reduce(lambda acc, x: acc * x, numbers, 1)
# Maximum
reduce(lambda acc, x: acc if acc > x else x, numbers)
# Flatten
reduce(lambda acc, lst: acc + lst, nested_lists, [])
When NOT to use:
- ❌ Simple sum →
sum() - ❌ Maximum/minimum →
max()/min() - ❌ Joining strings →
"".join()
What’s next?
Now you know reduce()! 🎉
Next topics:
- List comprehensions — an alternative to map/filter
- Pure functions — functions without side effects
- Pipeline — chaining map → filter → reduce
The holy trinity of functional programming:
1. map() — transform every element
2. filter() — select elements
3. reduce() — fold into a single value
Together they’re powerful! 🚀
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!