Learn Python / Lambda, map and filter

Lambda, map and filter

In Python, functions are values, just like numbers and strings. You can store them in variables, put them in lists and pass them to other functions. This lesson shows how, and introduces lambda, a quick way to write tiny functions on the spot.

Functions are values

A function name without () refers to the function itself, without calling it:

def shout(text):
    return text.upper() + "!"

yell = shout          # no parentheses: we're not calling it
print(yell("hello"))
print(type(shout))
Output

So you can pass a function into another function:

def apply_twice(func, value):
    return func(func(value))

def add_three(n):
    return n + 3

print(apply_twice(add_three, 10))
Output

Lambda functions

A lambda is a small function written in a single expression, without def or a name:

lambda parameters: expression

These two do the same thing:

def square(n):
    return n * n

square_lambda = lambda n: n * n

print(square(6))
print(square_lambda(6))
Output

A lambda can take several parameters, and its expression is returned automatically:

add = lambda a, b: a + b
full_name = lambda first, last: f"{first} {last}".title()

print(add(2, 3))
print(full_name("ada", "lovelace"))
Output

Lambdas are limited to one expression: no loops, no assignments, no multiple statements. Their real use is as short throwaway functions passed to other functions.

Sorting with a key

sorted(), min() and max() accept a key function. It's called on each item, and the results decide the order. This is where lambdas are used most:

words = ["banana", "Apple", "cherry", "date"]

print(sorted(words))                          # capitals first
print(sorted(words, key=str.lower))           # case-insensitive
print(sorted(words, key=len))                 # by length
print(sorted(words, key=lambda w: w[-1]))     # by last letter
Output

It's especially handy for lists of tuples or dictionaries:

students = [("Mia", 88), ("Leo", 95), ("Ava", 72)]

by_score = sorted(students, key=lambda s: s[1], reverse=True)
print(by_score)

best = max(students, key=lambda s: s[1])
print("Top student:", best[0])
Output
products = [
    {"name": "Laptop", "price": 999},
    {"name": "Mouse", "price": 25},
    {"name": "Monitor", "price": 249},
]

cheapest_first = sorted(products, key=lambda p: p["price"])
for p in cheapest_first:
    print(p["name"], p["price"])
Output

map(): apply a function to every item

map(function, iterable) calls the function on each item. It returns a lazy map object, so wrap it in list() to see the results:

numbers = [1, 2, 3, 4]

doubled = map(lambda n: n * 2, numbers)
print(doubled)          # a map object
print(list(doubled))

print(list(map(str.upper, ["a", "b", "c"])))
print(list(map(int, ["10", "20", "30"])))   # convert strings to ints
Output

A common trick reads several numbers from one line of input:

line = "3 8 15 4"
numbers = list(map(int, line.split()))
print(numbers, sum(numbers))
Output

filter(): keep the items that pass a test

filter(function, iterable) keeps the items for which the function returns something truthy:

numbers = [5, 12, 7, 20, 3, 18]

big = filter(lambda n: n > 10, numbers)
print(list(big))

words = ["", "hello", "", "world"]
print(list(filter(None, words)))   # None keeps only truthy items
Output

Comprehensions are often clearer

Anything map and filter do, a list comprehension can do too, and many Python programmers find the comprehension easier to read:

numbers = [5, 12, 7, 20, 3, 18]

print(list(map(lambda n: n * 2, numbers)))
print([n * 2 for n in numbers])

print(list(filter(lambda n: n > 10, numbers)))
print([n for n in numbers if n > 10])
Output

A good rule of thumb:

  • Use map when you already have a named function: map(int, parts).
  • Use a comprehension when you'd need a lambda.
  • Use a lambda mostly for key= arguments.
Going deeper: any() and all() optional

Two more built-ins answer yes-or-no questions about a whole collection:

  • any(items) is True if at least one item is truthy.
  • all(items) is True if every item is truthy.

They pair nicely with a comprehension that turns each item into True or False:

scores = [72, 85, 90, 66]

print(any(s >= 90 for s in scores))   # did anyone get 90 or more?
print(all(s >= 50 for s in scores))   # did everyone pass?
print(all(s >= 70 for s in scores))
Output

Notice there are no square brackets inside any() and all(). That's a generator expression, which you'll meet in Iterators and Generators. Writing any([s >= 90 for s in scores]) with brackets works too.

Both stop as soon as they know the answer, so any() stops at the first True. On an empty collection, any([]) is False and all([]) is True, because no item breaks the rule.

Exercises

Exercise 1: Sort by length

Sort the names from shortest to longest using sorted() with a key. It should print ['Al', 'Mia', 'Grace', 'Alexander'].

names = ["Grace", "Al", "Alexander", "Mia"]
Output

Exercise 2: Most expensive item

Use max() with a lambda to find the most expensive item, and print its name: Laptop.

items = [("Pen", 1.5), ("Laptop", 899.0), ("Book", 12.99)]
Output

Exercise 3: map and filter

Use filter to keep the odd numbers, then map to square them, and print the list: [1, 9, 25, 49, 81].

numbers = list(range(1, 11))
Output

Exercise 4: Rewrite as a comprehension

Rewrite the map/filter line as a single list comprehension that gives the same result.

words = ["python", "is", "fun", "and", "powerful"]

result = list(map(str.upper, filter(lambda w: len(w) > 3, words)))
print(result)
Output

Functions that take functions at a glance

A quick reference for later. The examples use words = ["kiwi", "fig", "banana"] and nums = [3, -5, 2].

Tool What it does Example Result
lambda args: expr A small one-line function (lambda x: x * 2)(5) 10
sorted(items, key=f) Sorts by f(item) instead of the item itself sorted(words, key=len) ['fig', 'kiwi', 'banana']
sorted(items, key=f, reverse=True) The same, largest first sorted(words, key=len, reverse=True) ['banana', 'kiwi', 'fig']
items.sort(key=f) Like sorted(), but sorts the list in place words.sort(key=len) words becomes ['fig', 'kiwi', 'banana']
min(items, key=f) The item with the smallest f(item) min(nums, key=abs) 2
max(items, key=f) The item with the largest f(item) max(words, key=len) 'banana'
map(f, items) Applies f to every item list(map(abs, nums)) [3, 5, 2]
filter(f, items) Keeps the items where f(item) is truthy list(filter(lambda n: n > 0, nums)) [3, 2]
filter(None, items) Keeps only the truthy items list(filter(None, [0, 1, "", "a"])) [1, 'a']
any(...) Is at least one item truthy? any(n < 0 for n in nums) True
all(...) Is every item truthy? all(n < 0 for n in nums) False

Summary

  • Functions are values: you can store them and pass them to other functions.
  • lambda params: expression makes a small one-expression function.
  • sorted, min and max take a key= function that decides the order.
  • map(func, items) transforms every item, and filter(func, items) keeps the items that pass.
  • Wrap map and filter in list() to see the results.
  • When you'd need a lambda, a list comprehension is often clearer.