Python Functional Programming
A Higher-Order Function is a function that takes one or more functions as arguments, or returns a function as its result. Functional programming treats computation as the evaluation of mathematical pure functions and avoids mutable shared state.
Python provides three classic functional primitives: map(), filter(), and reduce().
# Higher-Order Function taking an operation function as an argument:
def apply_transformation(data_list, transform_func):
return [transform_func(item) for item in data_list]
prices = [100, 250, 400]
gst_prices = apply_transformation(prices, lambda p: p * 1.18)
discounted_prices = apply_transformation(prices, lambda p: p * 0.90)
print("Original Prices: ", prices)
print("With 18% GST: ", gst_prices)
print("With 10% Discount: ", discounted_prices)
Instead of writing imperative for-loops with index counters, higher-order functions allow you to declare what transformation to perform.
Both map() and filter() return lazy iterators in Python 3, consuming zero memory until iterated:
map(func, iterable): Appliesfuncto every item in the collection.filter(func, iterable): Keeps only elements for whichfunc(item)evaluates to True.
# Raw student test scores:
scores = [45, 88, 92, 35, 78, 60, 95]
# 1. filter() passing students (score >= 50):
passing_scores = list(filter(lambda s: s >= 50, scores))
print("Passing Scores (>= 50):", passing_scores)
# 2. map() converting raw scores to percentages with bonus +5:
curved_scores = list(map(lambda s: min(100, s + 5), passing_scores))
print("Curved Scores (+5 bonus):", curved_scores)
While [s+5 for s in scores if s>=50] is often preferred in modern Python for readability, map and filter shine when combining pre-existing named functions (e.g. list(map(str.strip, lines))).
reduce(function, sequence, [initial]) (from the functools module) applies a rolling two-argument function cumulatively across all elements from left to right, reducing the entire collection to a single scalar value:
from functools import reduce
numbers = [1, 2, 3, 4, 5]
# 1. Calculate factorial / product of all numbers:
product = reduce(lambda acc, val: acc * val, numbers)
print("Product of [1..5]:", product) # 120
# 2. Find the maximum element using reduce:
raw_vals = [42, 17, 99, 23, 85]
max_val = reduce(lambda a, b: a if a > b else b, raw_vals)
print("Max value via reduce:", max_val) # 99
You can pass an optional initial accumulator: reduce(func, seq, 100) starts aggregation with 100.
In Python 2, map() and filter() returned lists. In Python 3, they return lazy iterators! Printing map(...) will output "
Use filter() to extract all words starting with the letter "P" (case-insensitive) from a list of words, and use map() to uppercase them.
words = ["python", "java", "Pandas", "c++", "PyTorch", "rust"]
p_words = list(map(str.upper, filter(lambda w: w.lower().startswith("p"), words)))
print("Cleaned P-words:", p_words)
Q Why was reduce() moved from built-in scope to functools in Python 3?
Guido van Rossum moved reduce() to functools because explicit for-loops or dedicated built-ins like sum(), any(), and all() are almost always more readable and Pythonic for 99% of use cases.
Q Can map() take multiple iterable arguments simultaneously?
Yes! map(lambda a, b: a + b, list1, list2) adds elements from both lists pairwise in parallel, stopping when the shortest iterable exhausts.
Q What is the difference between list comprehensions and map() in speed?
When using a lambda function, list comprehensions are faster due to bytecode optimizations. When passing an existing built-in C function (like map(int, str_list)), map() is slightly faster.