Lesson 146 min read

Lambda, Map & Filter

Tiny throwaway functions that pack a punch

Lambda Functions — One-Line Wonders

A lambda is a mini function that's too small to deserve a name. Think of it like a sticky note with a quick instruction: "double this number" or "is this even?" You use it, then throw it away.

The syntax is: lambda parameters: expression

Key rules:

  • Only one expression — no statements, no if/for blocks, no assignments.
  • Returns the result of that expression automatically (no return keyword).
  • Best used as a quick argument to functions like sorted(), map(), and filter().

Lambda Basics

# Regular function
def double(x):
return x * 2
# Same thing as a lambda
double_lambda = lambda x: x * 2
print(double(5)) # 10
print(double_lambda(5)) # 10
# Lambda with multiple parameters
add = lambda a, b: a + b
print(add(3, 7)) # 10
# Lambda with a conditional expression
category = lambda age: "adult" if age >= 18 else "minor"
print(category(25)) # adult
print(category(12)) # minor
# Most useful: inline with sorted()
students = [("Alice", 92), ("Bob", 85), ("Charlie", 97)]
by_score = sorted(students, key=lambda s: s[1], reverse=True)
print(by_score)
Output
10
10
10
adult
minor
[('Charlie', 97), ('Alice', 92), ('Bob', 85)]

map() — Transform Every Item

map() takes a function and applies it to every item in an iterable, like sending every item through a machine. It returns a map object (lazy), so wrap it in list() to see the results.

Pattern: map(function, iterable)

It's basically a functional programming alternative to list comprehensions. Use whichever reads better in context.

map() in Action

# Square every number
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print("Squared:", squared)
# Convert strings to integers
str_numbers = ["10", "20", "30", "40"]
int_numbers = list(map(int, str_numbers)) # Built-in function as argument!
print("Integers:", int_numbers)
# Temperature conversion: Celsius → Fahrenheit
celsius = [0, 20, 37, 100]
fahrenheit = list(map(lambda c: round(c * 9/5 + 32, 1), celsius))
print("Fahrenheit:", fahrenheit)
# map with multiple iterables
names = ["alice", "bob", "charlie"]
greetings = ["hi", "hello", "hey"]
result = list(map(lambda g, n: f"{g.title()}, {n.title()}!", greetings, names))
print(result)
Output
Squared: [1, 4, 9, 16, 25]
Integers: [10, 20, 30, 40]
Fahrenheit: [32.0, 68.0, 98.6, 212.0]
['Hi, Alice!', 'Hello, Bob!', 'Hey, Charlie!']

filter() — Keep Only What Passes

filter() is like a bouncer at a club — it checks every item against a condition and only lets the ones that return True through.

Pattern: filter(function, iterable)

The function should return True (keep) or False (reject) for each item.

filter() and reduce()

# Filter even numbers
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print("Evens:", evens)
# Filter non-empty strings
words = ["", "hello", "", "world", " ", "python"]
non_empty = list(filter(lambda w: w.strip(), words))
print("Non-empty:", non_empty)
# Filter passing scores
scores = {"Alice": 92, "Bob": 58, "Charlie": 74, "Diana": 45, "Eve": 88}
passing = dict(filter(lambda item: item[1] >= 60, scores.items()))
print("Passing:", passing)
# reduce() — combine all items into one value
from functools import reduce
nums = [1, 2, 3, 4, 5]
product = reduce(lambda a, b: a * b, nums)
print(f"\nProduct of {nums}: {product}") # 1*2*3*4*5 = 120
# reduce to find longest word
words = ["cat", "elephant", "dog", "hippopotamus", "ant"]
longest = reduce(lambda a, b: a if len(a) > len(b) else b, words)
print(f"Longest word: {longest}")
Output
Evens: [2, 4, 6, 8, 10]
Non-empty: ['hello', 'world', 'python']
Passing: {'Alice': 92, 'Charlie': 74, 'Eve': 88}

Product of [1, 2, 3, 4, 5]: 120
Longest word: hippopotamus

sorted() with key — Custom Sorting

The key parameter in sorted() is where lambda really shines. You give it a function that extracts the "sort value" from each item. Python uses these extracted values to determine the order.

Custom Sorting with key

# Sort strings by length
fruits = ["banana", "kiwi", "strawberry", "fig", "apple"]
by_length = sorted(fruits, key=lambda f: len(f))
print("By length:", by_length)
# Sort dicts by a specific field
students = [
{"name": "Alice", "gpa": 3.8},
{"name": "Bob", "gpa": 3.2},
{"name": "Charlie", "gpa": 3.9},
{"name": "Diana", "gpa": 3.5},
]
honor_roll = sorted(students, key=lambda s: s["gpa"], reverse=True)
for s in honor_roll:
print(f" {s['name']}: {s['gpa']}")
# Sort by multiple criteria (GPA desc, then name asc)
students.append({"name": "Eve", "gpa": 3.8})
multi_sort = sorted(students, key=lambda s: (-s["gpa"], s["name"]))
print("\nMulti-sort:")
for s in multi_sort:
print(f" {s['name']}: {s['gpa']}")
Output
By length: ['fig', 'kiwi', 'apple', 'banana', 'strawberry']
  Charlie: 3.9
  Alice: 3.8
  Diana: 3.5
  Bob: 3.2

Multi-sort:
  Charlie: 3.9
  Alice: 3.8
  Eve: 3.8
  Diana: 3.5
  Bob: 3.2
Note: Lambda vs. comprehension? For simple transforms, [x**2 for x in nums] is usually more readable than list(map(lambda x: x**2, nums)). But when you're passing a function to sorted(key=...) or a callback, lambda is the perfect tool.

Quick check

What does lambda x, y: x + y create?
Modules & ImportsDecorators & Closures