Lambda & Higher-Order Functions
📖 Concept
Lambda functions are anonymous, single-expression functions. They're useful for short callbacks and key functions but should not replace named functions for complex logic.
lambda arguments: expression
Higher-order functions are functions that take other functions as arguments or return functions. Python has several built-in higher-order functions:
| Function | Purpose | Example |
|---|---|---|
map(func, iterable) |
Apply func to each item | map(str, [1,2,3]) |
filter(func, iterable) |
Keep items where func returns True | filter(bool, [0,1,"",3]) |
sorted(iterable, key=func) |
Sort using func for comparison | sorted(words, key=len) |
min/max(iterable, key=func) |
Find min/max using func | max(users, key=lambda u: u.age) |
reduce(func, iterable) |
Cumulative operation | reduce(add, [1,2,3,4]) |
Important: map() and filter() return lazy iterators (not lists). They only compute values when iterated.
List comprehensions vs map/filter:
In most cases, list comprehensions are preferred over map() and filter() in Python because they're more readable and Pythonic. Use map()/filter() when you already have a named function to apply.
functools module provides powerful higher-order function utilities:
functools.reduce()— cumulative binary operationsfunctools.partial()— freeze some function argumentsfunctools.lru_cache()— memoization decoratorfunctools.singledispatch()— function overloading by type
💻 Code Example
1# ============================================================2# Lambda functions3# ============================================================4# Basic lambda5square = lambda x: x ** 26print(square(5)) # 2578# Multiple arguments9add = lambda a, b: a + b10print(add(3, 4)) # 71112# With default arguments13greet = lambda name, greeting="Hello": f"{greeting}, {name}!"14print(greet("Alice")) # "Hello, Alice!"15print(greet("Bob", "Hey")) # "Hey, Bob!"1617# Conditional expression in lambda18classify = lambda x: "positive" if x > 0 else "negative" if x < 0 else "zero"19print(classify(5)) # "positive"20print(classify(-3)) # "negative"21print(classify(0)) # "zero"2223# ============================================================24# map() — apply function to every item25# ============================================================26numbers = [1, 2, 3, 4, 5]2728# With lambda29doubled = list(map(lambda x: x * 2, numbers))30print(doubled) # [2, 4, 6, 8, 10]3132# With named function33def celsius_to_fahrenheit(c):34 return c * 9/5 + 323536temps_c = [0, 20, 37, 100]37temps_f = list(map(celsius_to_fahrenheit, temps_c))38print(temps_f) # [32.0, 68.0, 98.6, 212.0]3940# map with multiple iterables41a = [1, 2, 3]42b = [10, 20, 30]43sums = list(map(lambda x, y: x + y, a, b))44print(sums) # [11, 22, 33]4546# Equivalent list comprehension (preferred for simple cases)47doubled_comp = [x * 2 for x in numbers]4849# ============================================================50# filter() — keep items matching a condition51# ============================================================52numbers = range(-5, 6)5354# Keep positive numbers55positives = list(filter(lambda x: x > 0, numbers))56print(positives) # [1, 2, 3, 4, 5]5758# Filter with None removes falsy values59mixed = [0, 1, "", "hello", None, False, True, [], [1, 2]]60truthy = list(filter(None, mixed))61print(truthy) # [1, 'hello', True, [1, 2]]6263# Equivalent comprehension (preferred)64positives_comp = [x for x in numbers if x > 0]6566# ============================================================67# sorted() with key functions68# ============================================================69words = ["banana", "apple", "cherry", "date"]7071# Sort by length72by_length = sorted(words, key=len)73print(by_length) # ['date', 'apple', 'banana', 'cherry']7475# Sort by last character76by_last_char = sorted(words, key=lambda w: w[-1])77print(by_last_char) # ['banana', 'apple', 'date', 'cherry']7879# Sort complex objects80users = [81 {"name": "Charlie", "age": 35},82 {"name": "Alice", "age": 30},83 {"name": "Bob", "age": 25},84]8586by_age = sorted(users, key=lambda u: u["age"])87by_name = sorted(users, key=lambda u: u["name"])88print([u["name"] for u in by_age]) # ['Bob', 'Alice', 'Charlie']8990# Multi-key sorting91from operator import itemgetter92data = [("Alice", 30), ("Bob", 25), ("Alice", 25)]93sorted_data = sorted(data, key=itemgetter(0, 1)) # Sort by name, then age94print(sorted_data) # [('Alice', 25), ('Alice', 30), ('Bob', 25)]9596# ============================================================97# reduce() — cumulative operation98# ============================================================99from functools import reduce100101# Sum (though sum() built-in is better for this)102total = reduce(lambda acc, x: acc + x, [1, 2, 3, 4, 5])103print(total) # 15104105# Product106product = reduce(lambda acc, x: acc * x, [1, 2, 3, 4, 5])107print(product) # 120108109# Flatten nested lists110nested = [[1, 2], [3, 4], [5, 6]]111flat = reduce(lambda acc, lst: acc + lst, nested, [])112print(flat) # [1, 2, 3, 4, 5, 6]113114# Build a dict from pairs115pairs = [("a", 1), ("b", 2), ("c", 3)]116d = reduce(lambda acc, pair: {**acc, pair[0]: pair[1]}, pairs, {})117print(d) # {'a': 1, 'b': 2, 'c': 3}118119# ============================================================120# functools.partial — freeze some arguments121# ============================================================122from functools import partial123124def power(base, exponent):125 return base ** exponent126127square = partial(power, exponent=2)128cube = partial(power, exponent=3)129130print(square(5)) # 25131print(cube(3)) # 27132133# Practical: configure a function134import json135pretty_json = partial(json.dumps, indent=2, sort_keys=True)136print(pretty_json({"b": 2, "a": 1}))137138# ============================================================139# operator module — named versions of operators140# ============================================================141from operator import add, mul, itemgetter, attrgetter142143# Use instead of lambdas for simple operations144total = reduce(add, [1, 2, 3, 4, 5]) # Better than lambda a,b: a+b145product = reduce(mul, [1, 2, 3, 4, 5])146147# itemgetter for dict/tuple access148get_name = itemgetter("name")149users = [{"name": "Charlie"}, {"name": "Alice"}, {"name": "Bob"}]150sorted_users = sorted(users, key=get_name)151152# attrgetter for object attribute access153from collections import namedtuple154Person = namedtuple("Person", ["name", "age"])155people = [Person("Charlie", 35), Person("Alice", 30), Person("Bob", 25)]156sorted_people = sorted(people, key=attrgetter("age"))157print([p.name for p in sorted_people]) # ['Bob', 'Alice', 'Charlie']
🏋️ Practice Exercise
Exercises:
Use
map(),filter(), andreduce()to: take a list of strings, filter out empty ones, convert to uppercase, and concatenate with commas.Sort a list of dictionaries by multiple keys: first by "department" (ascending), then by "salary" (descending). Show both lambda and
operator.itemgetterapproaches.Implement
my_map(func, iterable)andmy_filter(func, iterable)using only reduce.Use
functools.partialto create a family of string formatting functions:format_currency,format_percentage,format_date.Compare performance: write the same operation using a for loop, list comprehension,
map()with lambda, andmap()with named function. Time each approach for a large list.Rewrite a complex reduce operation as a simple for loop. Argue which version is more readable and why.
⚠️ Common Mistakes
Overusing lambda for complex logic. If a lambda needs multiple operations or is hard to read, use a named
deffunction instead. Lambdas are for simple, one-expression operations.Forgetting that
map()andfilter()return iterators, not lists. Uselist(map(...))if you need a list. Iterators can only be consumed once.Using
map(lambda x: ..., items)when a list comprehension[... for x in items]would be clearer. Prefer comprehensions for simple transformations.Not knowing about
operator.itemgetterandoperator.attrgetter— these are faster and more readable alternatives to lambda for accessing attributes and items.Using
reduce()for operations that have simpler alternatives:sum()for addition,math.prod()for multiplication,''.join()for string concatenation,any()/all()for boolean reduction.
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for Lambda & Higher-Order Functions