map, filter & reduce
map, filter, and reduce are three functional-programming tools for working with iterables without writing an explicit loop. Each takes a function and applies it across a sequence, but they differ in what they produce: map transforms every element, filter selects a subset of elements, and reduce collapses the whole sequence down to a single value.
map: transform every element
map(func, iterable) applies func to every item in iterable and produces one
output per input. It does not return a list — it returns a lazy map object, which is
an iterator that computes each result only as it's requested. To see the results (or
use them like a list), wrap the call in list(...).
numbers = [1, 2, 3, 4, 5] doubled = map(lambda n: n * 2, numbers) print(doubled) # a map object, not a list print(list(doubled)) # materializes the results
<map object at 0x0000023F5B2A1A90> [2, 4, 6, 8, 10]
filter: select elements
filter(func, iterable) keeps only the items for which func returns a truthy
value, dropping the rest. Like map, it's lazy — it returns a filter object, and you
need list(...) (or a for loop, or another consumer) to actually pull the values out.
numbers = [1, 2, 3, 4, 5, 6, 7, 8] evens = filter(lambda n: n % 2 == 0, numbers) print(evens) # a filter object, not a list print(list(evens)) # materializes the results
<filter object at 0x0000023F5B2A1B20> [2, 4, 6, 8]
reduce: accumulate to a single value
reduce(func, iterable, initial) lives in the functools module rather than being a
builtin. Unlike map and filter, it does not return an iterator at all — it eagerly walks
the whole iterable and returns one final accumulated value. func must take two
arguments: the running accumulator and the next item.
from functools import reduce numbers = [1, 2, 3, 4, 5] total = reduce(lambda acc, n: acc + n, numbers, 0) print(total) product = reduce(lambda acc, n: acc * n, numbers, 1) print(product)
15 120
The third argument, initial, seeds the accumulator before the first call to func.
If you omit it, reduce uses the iterable's first element as the starting accumulator
and begins combining from the second element onward. That works fine for a non-empty
list, but calling reduce on an empty iterable with no initial raises a TypeError
— passing initial explicitly avoids that edge case.
from functools import reduce # without an initial value: the first element seeds the accumulator print(reduce(lambda acc, n: acc + n, [1, 2, 3, 4, 5])) # empty iterable + no initial value raises TypeError reduce(lambda acc, n: acc + n, [])
15 Traceback (most recent call last): ... TypeError: reduce() of empty iterable with no initial value
Laziness: the key difference
It's worth being precise about this, since the three functions are often lumped
together: map and filter both return lazy iterator objects — nothing is computed
until you iterate over them or wrap them in list(). reduce, on the other hand, does
not return an iterator at all; it immediately walks the entire iterable and hands back
one final value. There's no lazy "reduce object" to speak of.
map/filter vs. list comprehensions
Both map and filter have direct list comprehension equivalents, and most Python style guides favor the comprehension form for readability.
Goal | map / filter | List comprehension |
|---|---|---|
Double every number | list(map(lambda n: n * 2, numbers)) | [n * 2 for n in numbers] |
Keep only even numbers | list(filter(lambda n: n % 2 == 0, numbers)) | [n for n in numbers if n % 2 == 0] |
Double the even numbers | list(map(lambda n: n * 2, filter(lambda n: n % 2 == 0, numbers))) | [n * 2 for n in numbers if n % 2 == 0] |
Summary
map(func, iterable)transforms every element and returns a lazy iterator — wrap it inlist()to see the resultsfilter(func, iterable)keeps only elements wherefuncreturns truthy, also returning a lazy iteratorreduce(func, iterable, initial)fromfunctoolseagerly folds the iterable down to one value, not an iteratorOmitting reduce's initial value uses the first element as the seed, and raises
TypeErroron an empty iterableList comprehensions are usually the more readable choice for map/filter-style work; reduce has no comprehension equivalent