Skip to main content

04.3 - Lambda, map(), filter(), reduce()

Theory 20 min Intermediate

Lambda Functions

A lambda is an anonymous, single-expression function:

# Syntax
lambda parameters: expression

# Named lambda (unusual — prefer def for this)
square = lambda x: x ** 2
square(5) # 25

# Inline — most common use
sorted_words = sorted(words, key=lambda w: len(w))

# Multi-param
add = lambda a, b: a + b
add(3, 4) # 7

# With default
greet = lambda name, greeting="Hello": f"{greeting}, {name}!"

Lambda vs def

Lambdadef
Lines1 (expression only)Multiple
NameAnonymousNamed
DocstringNot supportedSupported
Best forInline key functionsReusable, documented functions
# ✅ Lambda — appropriate for key functions
students.sort(key=lambda s: (s["grade"], s["name"]))

# ❌ Lambda — avoid for complex logic
# bad: lambda x: x**2 if x > 0 else 0 (use def)

# ✅ def — for anything beyond simple expressions
def transform(x):
"""Square positive numbers, zero others."""
return x ** 2 if x > 0 else 0

map() — Transform Every Element

map(function, iterable) applies a function to every element and returns a lazy iterator.

numbers = [1, 2, 3, 4, 5]

# With lambda
squared = list(map(lambda x: x**2, numbers))
# [1, 4, 9, 16, 25]

# With named function
def celsius_to_fahrenheit(c):
return (c * 9/5) + 32

temps_c = [0, 20, 37, 100]
temps_f = list(map(celsius_to_fahrenheit, temps_c))
# [32.0, 68.0, 98.6, 212.0]

# Multiple iterables
a = [1, 2, 3]
b = [10, 20, 30]
sums = list(map(lambda x, y: x + y, a, b))
# [11, 22, 33]

# Modern equivalent (often more readable)
squared = [x**2 for x in numbers]

filter() — Keep Elements Matching a Condition

filter(function, iterable) keeps only elements where the function returns True.

numbers = range(-5, 6)   # -5 to 5

# With lambda
positives = list(filter(lambda x: x > 0, numbers))
# [1, 2, 3, 4, 5]

# Filter None (remove falsy values)
mixed = [1, None, 2, "", 3, False, 4, 0, 5]
truthy = list(filter(None, mixed))
# [1, 2, 3, 4, 5]

# With named function
def is_even(n):
return n % 2 == 0

evens = list(filter(is_even, range(10)))
# [0, 2, 4, 6, 8]

# Modern equivalent
evens = [n for n in range(10) if n % 2 == 0]

reduce() — Aggregate to a Single Value

reduce(function, iterable) applies a function cumulatively to produce a single result.

from functools import reduce

numbers = [1, 2, 3, 4, 5]

# Sum (don't use reduce for this — use sum())
total = reduce(lambda acc, x: acc + x, numbers) # 15

# Product
product = reduce(lambda acc, x: acc * x, numbers) # 120

# Maximum (don't use — use max())
maximum = reduce(lambda a, b: a if a > b else b, numbers) # 5

# With initial value
reduce(lambda acc, x: acc + x, numbers, 100) # 115 (100 + 1+2+3+4+5)

# Practical: flatten a list of lists
lists = [[1, 2], [3, 4], [5, 6]]
flat = reduce(lambda acc, lst: acc + lst, lists, [])
# [1, 2, 3, 4, 5, 6]

sorted() with key=

One of the most powerful uses of lambdas is as the key argument for sorting:

students = [
{"name": "Alice", "grade": 92, "age": 22},
{"name": "Bob", "grade": 85, "age": 24},
{"name": "Charlie", "grade": 92, "age": 21},
]

# Sort by grade descending
sorted(students, key=lambda s: s["grade"], reverse=True)

# Multi-key sort (primary: grade desc, secondary: name asc)
sorted(students, key=lambda s: (-s["grade"], s["name"]))

# Sort strings case-insensitively
words = ["Banana", "apple", "Cherry"]
sorted(words, key=str.lower) # ['apple', 'Banana', 'Cherry']

# Sort by length, then alphabetically
sorted(words, key=lambda w: (len(w), w.lower()))

any() and all()

numbers = [2, 4, 6, 8, 10]

all(n % 2 == 0 for n in numbers) # True — all are even
any(n > 9 for n in numbers) # True — at least one > 9
all(n > 9 for n in numbers) # False — not all > 9
any(n < 0 for n in numbers) # False — none are negative

# With lambda + map (less common)
all(map(lambda n: n > 0, numbers)) # True

zip() and enumerate() Revisited

# zip creates pairs
names = ["Alice", "Bob", "Charlie"]
scores = [92, 85, 78]

# Dict from two lists
grade_book = dict(zip(names, scores))
# {"Alice": 92, "Bob": 85, "Charlie": 78}

# Unzip (transpose)
pairs = [(1, "a"), (2, "b"), (3, "c")]
numbers, letters = zip(*pairs)
# numbers = (1, 2, 3), letters = ('a', 'b', 'c')

Functional vs Comprehension Style

Python prefers comprehensions over map/filter for readability:

FunctionalComprehensionPreferred
list(map(f, xs))[f(x) for x in xs]Comprehension
list(filter(p, xs))[x for x in xs if p(x)]Comprehension
reduce(op, xs)Use sum(), max(), etc.Built-in

But map()/filter() are still useful when:

  • Working with generators (lazy evaluation)
  • Passing as callbacks to other functions
  • Combining with zip() or itertools

Key Vocabulary

TermDefinition
LambdaAnonymous single-expression function: lambda x: x*2
map()Apply a function to all elements of an iterable (lazy)
filter()Keep elements where a function returns True (lazy)
reduce()Cumulatively apply a function to produce one value
sorted(key=)Sort by a custom key function
any()True if at least one element is truthy
all()True if all elements are truthy
Functional programmingProgramming style treating functions as first-class values

Summary

  • Lambda lambda params: expr creates inline anonymous functions — best for sort keys and callbacks
  • map(f, iter) applies f to every element; prefer list comprehensions for readability
  • filter(p, iter) keeps elements where p returns True; prefer comprehensions
  • reduce(op, iter) aggregates to one value; prefer sum(), max(), min() when possible
  • sorted(lst, key=lambda x: ...) enables powerful multi-key sorting
  • any() and all() pair perfectly with generator expressions