Skip to main content
Editor

Python map(), filter(), reduce(), and Higher-Order Functions

Intermediate25 min7 exercises100 XP

Leer en españolЧитать на русскомLer em portuguêsอ่านภาษาไทย

0/7 exercises

Picture an assembly line in a factory. Raw materials enter at one end. At the first station, each piece is shaped. At the next station, defective pieces are removed. At the final station, all the good pieces are combined into one finished product.

Python has three functions that work exactly like this assembly line: map() transforms every item, filter() keeps only the items you want, and reduce() combines everything into a single result. Together, they let you process collections of data in a clean, readable way.

In this tutorial, you'll learn how these tools work, when to use them, and when a list comprehension might be a better choice. By the end, you'll be writing data pipelines that would make a factory foreman proud.

What Are Higher-Order Functions?

A higher-order function is a function that takes another function as an argument, or returns a function as its result. That's it.

You've already used one without realizing it. The built-in sorted() function has a key parameter where you pass in a function:

sorted() is a higher-order function
words = ["banana", "apple", "cherry"]
# sorted() is a higher-order function
# It takes len as an argument - a function!
sorted_words = sorted(words, key=len)
print(sorted_words)
Output
['apple', 'banana', 'cherry']

Here, len is passed as an argument to sorted(). The sorted function calls len on each item to decide the order. You didn't call len() yourself - you just told sorted which function to use.

map(), filter(), and reduce() all work this way. You give them a function and a collection, and they apply that function to the items. That's what makes them higher-order functions.

map(): Transform Every Item

map() takes a function and an iterable (like a list), applies the function to every item, and returns the transformed results. Think of it as the "shaping station" on our assembly line.

The syntax is: map(function, iterable). It returns a map object, which you usually convert to a list.

Using map() to double every number
numbers = [1, 2, 3, 4, 5]
# Double every number
def double(x):
return x * 2
result = list(map(double, numbers))
print(result)
Output
[2, 4, 6, 8, 10]

map(double, numbers) calls double(1), double(2), double(3), and so on. It collects all the results. The list() wrapper converts the map object into a regular list so we can print it.

Since writing a whole function just to double a number feels heavy, map() is often paired with a lambda - a tiny anonymous function:

map() with lambda and built-in functions
numbers = [1, 2, 3, 4, 5]
# Same thing, but with a lambda
result = list(map(lambda x: x * 2, numbers))
print(result)
# More examples
names = ["alice", "bob", "charlie"]
print(list(map(str.upper, names)))
prices = [10.5, 20.3, 5.99]
print(list(map(round, prices)))
Output
[2, 4, 6, 8, 10]
['ALICE', 'BOB', 'CHARLIE']
[10, 20, 6]

You can pass any function to map() - your own functions, lambdas, or built-ins like str.upper, round, len, or int.

filter(): Keep Only What You Need

filter() takes a function and an iterable. The function must return True or False for each item. Only items where the function returns True are kept. Think of it as quality control on the assembly line - defective pieces are removed.

Using filter() to keep even numbers
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Keep only even numbers
def is_even(x):
return x % 2 == 0
result = list(filter(is_even, numbers))
print(result)
Output
[2, 4, 6, 8, 10]

filter(is_even, numbers) calls is_even(1) which returns False (so 1 is dropped), is_even(2) returns True (so 2 is kept), and so on. Only the items that pass the test survive.

More filter() examples
words = ["hello", "", "world", "", "python", ""]
# Remove empty strings - filter with bool
result = list(filter(bool, words))
print(result)
# Keep words longer than 4 characters
long_words = list(filter(lambda w: len(w) > 4, words))
print(long_words)
# Keep positive numbers
numbers = [-3, -1, 0, 2, 5, -4, 8]
positives = list(filter(lambda x: x > 0, numbers))
print(positives)
Output
['hello', 'world', 'python']
['hello', 'world', 'python']
[2, 5, 8]

Passing bool to filter() is a neat trick. Empty strings, zero, None, and empty lists are all "falsy" in Python - bool() returns False for them. So filter(bool, items) removes all falsy values.

Combining map() and filter()

The real power comes from chaining these together. Filter first to select items, then map to transform them - just like stations on an assembly line.

Chaining filter() and map()
scores = [45, 82, 91, 67, 55, 38, 73, 88, 95, 60]
# Step 1: Filter passing scores (>= 60)
passing = filter(lambda s: s >= 60, scores)
# Step 2: Add 5 bonus points to each passing score
boosted = map(lambda s: s + 5, passing)
# Convert to list and print
result = list(boosted)
print(result)
Output
[87, 96, 72, 78, 93, 100, 65]

Since both filter() and map() are lazy, you can chain them without creating intermediate lists. The data flows through the pipeline efficiently.

Here is a more practical example - processing a list of product prices:

Practical pipeline: filter then transform
prices = [12.99, 5.50, 89.99, 3.25, 45.00, 2.99, 150.00]
# Keep prices over $10, then apply 20% discount
result = list(
map(
lambda p: round(p * 0.8, 2),
filter(lambda p: p > 10, prices)
)
)
print(result)
Output
[10.39, 71.99, 36.0, 120.0]

reduce(): Combine All Items Into One

reduce() takes a function and an iterable, then combines all items into a single value. It's the final station on the assembly line - all the pieces get assembled into one product.

Unlike map() and filter(), reduce() is not a built-in. You need to import it from the functools module.

Using reduce() to combine values
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# Sum all numbers: ((((1+2)+3)+4)+5) = 15
total = reduce(lambda a, b: a + b, numbers)
print(f"Sum: {total}")
# Multiply all numbers: ((((1*2)*3)*4)*5) = 120
product = reduce(lambda a, b: a * b, numbers)
print(f"Product: {product}")
Output
Sum: 15
Product: 120

Here's how reduce() works step by step for the sum. The function takes two arguments: the accumulated result so far (a) and the next item (b):

  • Start with the first two items: a=1, b=2 gives 3
  • Take that result and the next item: a=3, b=3 gives 6
  • Continue: a=6, b=4 gives 10
  • Finally: a=10, b=5 gives 15
  • More reduce() examples
    from functools import reduce
    # Find the longest word
    words = ["cat", "elephant", "dog", "hippopotamus"]
    longest = reduce(lambda a, b: a if len(a) >= len(b) else b, words)
    print(f"Longest word: {longest}")
    # Join words with a separator
    result = reduce(lambda a, b: f"{a} & {b}", ["Alice", "Bob", "Charlie"])
    print(result)
    Output
    Longest word: hippopotamus
    Alice & Bob & Charlie

    map/filter vs List Comprehensions

    Python offers another way to transform and filter lists: list comprehensions. They often produce more readable code than map() and filter(). Let's compare.

    Using map() and filter()
    numbers = [1, 2, 3, 4, 5, 6]
    
    # Double even numbers
    evens = filter(lambda x: x % 2 == 0, numbers)
    result = list(map(lambda x: x * 2, evens))
    print(result)  # [4, 8, 12]
    Using a list comprehension
    numbers = [1, 2, 3, 4, 5, 6]
    
    # Double even numbers
    result = [x * 2 for x in numbers if x % 2 == 0]
    print(result)  # [4, 8, 12]

    The list comprehension does both filtering and mapping in a single, readable line. For simple transformations, comprehensions are usually the better choice in Python.

    So when should you use map() and filter()? They're useful when you already have a named function to apply:

    map() shines with named functions
    # When you have a named function, map() reads nicely
    names = ["alice", "bob", "charlie"]
    print(list(map(str.capitalize, names)))
    # Equivalent comprehension - a bit more verbose
    print([name.capitalize() for name in names])
    Output
    ['Alice', 'Bob', 'Charlie']
    ['Alice', 'Bob', 'Charlie']

    Practice Exercises

    Time to practice. These exercises start with individual functions and build up to combining them in pipelines. Remember to wrap map() and filter() in list() when printing.

    Exercise 1: Square Every Number
    Write Code

    Use map() with a lambda to square every number in the list [1, 2, 3, 4, 5].

    Print the result as a list.

    Expected output:

    [1, 4, 9, 16, 25]
    numbers = [1, 2, 3, 4, 5]
    # Use map() to square each number
    Exercise 2: Filter Out Short Words
    Write Code

    Use filter() with a lambda to keep only words that have more than 3 characters.

    Given: ["hi", "hello", "hey", "world", "ok", "python"]

    Print the result as a list.

    Expected output:

    ['hello', 'world', 'python']
    words = ["hi", "hello", "hey", "world", "ok", "python"]
    # Use filter() to keep words longer than 3 characters
    Exercise 3: Predict the Pipeline Output
    Predict Output

    Read this code and predict the output. Then write a print() statement that produces the exact same output.

    numbers = [10, 25, 30, 45, 50]
    result = list(map(lambda x: x // 10, filter(lambda x: x >= 30, numbers)))
    print(result)

    Think step by step: what does filter keep, then what does map do to each item?

    # Print the exact output
    Exercise 4: Fix the Broken Pipeline
    Fix the Bug

    This code should convert a list of temperature strings like ["32F", "100F", "212F"] into Celsius integers. But it has two bugs.

    Expected output:

    [0, 38, 100]

    Formula: Celsius = (Fahrenheit - 32) * 5 / 9, then round to the nearest integer.

    temps = ["32F", "100F", "212F"]
    # Bug 1: Need to extract the number from the string
    # Bug 2: Formula or conversion issue
    result = list(map(lambda t: int((t - 32) * 5 / 9), temps))
    print(result)
    Exercise 5: Find the Product with reduce()
    Write Code

    Use reduce() from the functools module to calculate the product of all numbers in the list [2, 3, 4, 5].

    The product is 2 * 3 * 4 * 5 = 120.

    Print the result.

    Expected output:

    120
    from functools import reduce
    numbers = [2, 3, 4, 5]
    # Use reduce() to multiply all numbers together
    Exercise 6: Build a Data Pipeline
    Write Code

    Given a list of student scores, build a pipeline that:

    1. Filters out failing scores (keep only scores >= 60)

    2. Curves each passing score by adding 10 (use map)

    3. Caps scores at 100 (use map with min)

    Given: [45, 82, 55, 91, 67, 38, 73, 95]

    Print the final list.

    Expected output:

    [92, 100, 77, 83, 100]

    Hint: to cap at 100, use min(score, 100).

    scores = [45, 82, 55, 91, 67, 38, 73, 95]
    # Step 1: Filter passing scores (>= 60)
    # Step 2: Add 10 bonus points
    # Step 3: Cap at 100
    Exercise 7: Refactor to a List Comprehension
    Refactor

    Refactor this map/filter pipeline into a single list comprehension that produces the same output.

    Original code:

    words = ["Hello", "WORLD", "Python", "CODE", "test"]
    result = list(map(str.lower, filter(lambda w: len(w) > 4, words)))

    Write a list comprehension that produces the same result and print it.

    Expected output:

    ['hello', 'world', 'python']
    words = ["Hello", "WORLD", "Python", "CODE", "test"]
    # Refactor to a list comprehension
    result = [] # Replace with your comprehension
    print(result)

    Summary

    Here's what you've learned about functional tools in Python:

    FunctionPurposeReturns
    map(fn, iterable)Transform every itemMap object (lazy)
    filter(fn, iterable)Keep items where fn returns TrueFilter object (lazy)
    reduce(fn, iterable)Combine all items into one valueSingle value
    Higher-order functionA function that takes or returns a functionDepends on the function

    The practical takeaway: use list comprehensions for most transform/filter tasks in Python. Reach for map() and filter() when you have a named function to apply or need lazy evaluation. Use reduce() sparingly - Python's built-ins cover most cases better.

    What's Next?

    You now have a strong foundation in Python functions. Next, explore Error Handling to learn how to write code that handles mistakes gracefully instead of crashing.

    Harder problems

    More problems on this topic: Functions

    Related Tutorials

    Was this tutorial helpful?