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!
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]
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']
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']
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
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.
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
Complete Lambda Syntax
lambda parameters: expression
# ↑ Equivalent to
def anonymous_function(parameters):
return expression
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
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
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.
⚠️ Q: Can lambda span multiple lines? A: No. Lambda syntax is restricted to single expressions. For multi-line logic, define a regular function. Python's lambda is deliberately weaker than in other languages (like JavaScript) — Guido (Python's creator) believes "explicit is better than implicit."
Q: Is reduce() still used in modern Python? A: Not very much. Guido himself wasn't fond of 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.



