Python: Higher-Order Functions and Lambda
In Python, functions are also "values" — they can be assigned to variables, passed to other functions, just like numbers and strings. This enables very concise and elegant code. Higher-order functions are functions that take other functions as arguments or return functions. This lesson will open a new world for you.
1. Functions Are First-Class Citizens
In Python, functions can be manipulated like any other value:
▶ Example: Functions as Values
def say_hello(name):
return f"Hello, {name}"
# Assign a function to a variable
my_func = say_hello
print(my_func("Alice")) # Hello, Alice
# Pass a function as an argument
def greet_with(func, name):
return func(name)
print(greet_with(say_hello, "Bob")) # Hello, Bob
# Return a function from a function
def create_greeter(greeting):
def greeter(name):
return f"{greeting}, {name}!"
return greeter
say_hi = create_greeter("Hi")
say_hello = create_greeter("Hello")
print(say_hi("Alice")) # Hi, Alice!
print(say_hello("Bob")) # Hello, Bob!
Output:
# Function defined successfully
2. map(): Batch Transformation
map() applies a function to every element in a sequence and returns a new iterator:
▶ Example: map Batch Transform
# Square each number in a list
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared) # [1, 4, 9, 16, 25]
# Convert string list to uppercase
fruits = ["apple", "banana", "cherry"]
upper_fruits = list(map(str.upper, fruits))
print(upper_fruits) # ['APPLE', 'BANANA', 'CHERRY']
# Celsius to Fahrenheit
temps_c = [0, 10, 20, 30, 40]
temps_f = list(map(lambda c: c * 9 / 5 + 32, temps_c))
print(temps_f) # [32.0, 50.0, 68.0, 86.0, 104.0]
Output:
# Executed successfully
map()is equivalent to a list comprehension:map(f, seq)≈[f(x) for x in seq]. Which to use is a matter of preference — comprehensions are more "Pythonic."
3. filter(): Batch Filtering
filter() selects elements for which the function returns True:
▶ Example: filter Data
# 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) # [2, 4, 6, 8, 10]
# Filter words with length >= 5
words = ["cat", "elephant", "dog", "giraffe", "ant"]
long_words = list(filter(lambda w: len(w) >= 5, words))
print(long_words) # ['elephant', 'giraffe']
# Filter non-empty strings
data = ["hello", "", "world", "", "python"]
non_empty = list(filter(None, data)) # None means "remove falsy values"
print(non_empty) # ['hello', 'world', 'python']
Output:
# Executed successfully
filter()is also equivalent to a comprehension:filter(f, seq)≈[x for x in seq if f(x)]. UsingNoneas the function is equivalent to removing all falsy values ("",0,None,False, etc.).
4. Advanced sorted() Usage
Lesson 11 covered sorted()'s key parameter. Let's go deeper:
▶ Example: Custom Sorting with sorted
# Sort by object attribute
students = [
{"name": "Alice", "score": 85},
{"name": "Bob", "score": 92},
{"name": "Charlie", "score": 78},
]
# Sort by score descending
ranked = sorted(students, key=lambda s: s["score"], reverse=True)
for s in ranked:
print(f"{s['name']}: {s['score']}")
# Sort by name length
sorted_by_name = sorted(students, key=lambda s: len(s["name"]))
print([s["name"] for s in sorted_by_name]) # ['Alice', 'Bob', 'Charlie']
Output:
# Executed successfully
▶ Example: Multi-Level Sorting (Difficulty ⭐⭐)
# Sort by score descending, then by name alphabetically
data = [
("Alice", 85),
("Bob", 92),
("Charlie", 85),
("Diana", 92),
]
def sort_key(item):
# Return tuple: first by score descending (negative = reverse), then by name
return (-item[1], item[0])
sorted_data = sorted(data, key=sort_key)
for name, score in sorted_data:
print(f"{name}: {score}")
Output:
Bob: 92
Diana: 92
Alice: 85
Charlie: 85
5. reduce(): Cumulative Computation
reduce() accumulates elements in a sequence, applying a function to two elements at a time. It's not a built-in; import from functools:
▶ Example: reduce Cumulative Computation
from functools import reduce
# Product of all numbers
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product) # 120 (1×2×3×4×5)
# Find maximum
max_val = reduce(lambda a, b: a if a > b else b, [3, 1, 4, 1, 5])
print(max_val) # 5
# Concatenate strings
words = ["Hello", " ", "World", " ", "Python"]
sentence = reduce(lambda a, b: a + b, words)
print(sentence) # Hello World Python
Output:
# Executed successfully
(1) Execution Process of reduce()
# reduce(lambda x, y: x + y, [1, 2, 3, 4])
# Step 1: x=1, y=2 → 3
# Step 2: x=3, y=3 → 6
# Step 3: x=6, y=4 → 10
# Result: 10
reduce() vs loops: Anything reduce() can do, a for loop can also do. reduce() is more concise and declarative — you're saying "what to do" rather than "how to do it." The downside is it can be harder to understand for newcomers.
6. Lambda Expressions Deep Dive
Lambda, named after the Greek letter λ, is essentially an anonymous function — a small function without a name, used and discarded.
(1) Lambda vs Regular Functions
▶ Example: Lambda vs Regular
# Regular function
def double(x):
return x * 2
# Lambda expression
double = lambda x: x * 2
print(double(5)) # 10
Output:
# Function defined successfully
(2) Complete Lambda Syntax
lambda parameters: expression
# ↑ Equivalent to
def anonymous_function(parameters):
return expression
(3) Multiple Parameters
▶ Example: Lambda with Multiple Parameters
add = lambda a, b: a + b
print(add(3, 5)) # 8
# Ternary expression in lambda
max_val = lambda a, b: a if a > b else b
print(max_val(10, 20)) # 20
Output:
# Executed successfully
(4) When to Use Lambda
▶ Example: Lambda Use Cases
# ✅ Good: simple one-line transformation as argument to higher-order function
numbers = [1, 2, 3, 4]
result = list(map(lambda x: x ** 2, numbers))
# ❌ Bad: complex logic requiring multiple lines — use a regular def function instead
Output:
# Function defined successfully
7. Common Use Cases
- Data pipelines: Chain
map()→filter()→sorted()for data processing. - Custom sorting: Use
lambdaas thekeyparameter for various sort rules. - Event callbacks: Pass functions as arguments to GUI or web frameworks.
- Closure factories: Outer function returns inner function for "parameterized" functionality.
- Lazy evaluation: Higher-order functions defer computation until needed.
❓ FAQ
map() or list comprehensions?map() has advantages: ① Shorter when you have an existing function name (map(str.upper, seq) vs [s.upper() for s in seq]); ② Returns a lazy iterator, saving memory for large data. In most cases, list comprehensions are the better choice.reduce() still used in modern Python?reduce(), finding it hard to understand. Most reduce() scenarios can be replaced with a loop or a more direct function (like sum(), max()). However, reduce() remains an important concept in functional programming.📖 Summary
- Functions are first-class citizens in Python — can be assigned, passed, and returned
map(f, seq)applies a function to each element; uselist()to convert to a listfilter(f, seq)selects elements where the function returns Truesorted(seq, key=f)accepts a function for custom sortingreduce(f, seq)accumulates values; import fromfunctools- Lambda
lambda params: expressionis an anonymous single-line function for simple scenarios
📝 Exercises
-
Basic (Difficulty ⭐): Given
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], usemap()andfilter()to: filter odd numbers and compute their squares. Hint: Firstfilterfor odds, thenmapto square. -
Intermediate (Difficulty ⭐⭐): Given a list of dicts
products = [{"name": "A", "price": 100}, {"name": "B", "price": 80}, {"name": "C", "price": 120}], usesorted()to sort by price descending and output names and prices. -
Challenge (Difficulty ⭐⭐⭐): Use
reduce()to implement aflatten(nested_list)function that flattens a nested list by one level. For example,flatten([[1, 2], [3, 4], [5]])returns[1, 2, 3, 4, 5]. Hint: Inreduce, use+to merge two lists each time. Then implement the same with a list comprehension and compare the approaches.