Skip to main content

Module 16 - Functional Programming

Functional programming treats computation as the evaluation of mathematical functions and avoids changing state. Python supports functional programming through lambda functions, map, filter, reduce, and higher-order functions.


1. Lambda Functions

Lambda functions are anonymous, one-line functions defined using the lambda keyword.

Syntax

lambda arguments: expression

Basic Examples

# Regular function
def square(x):
return x ** 2

# Lambda equivalent
square = lambda x: x ** 2

print(square(5)) # 25

# Multiple arguments
add = lambda x, y: x + y
print(add(3, 7)) # 10

# No arguments
get_pi = lambda: 3.14159
print(get_pi()) # 3.14159

Common Use Cases

# Sorting with custom key
students = [
{'name': 'Alice', 'grade': 88},
{'name': 'Bob', 'grade': 95},
{'name': 'Charlie', 'grade': 82}
]

# Sort by grade
sorted_students = sorted(students, key=lambda s: s['grade'])
print(sorted_students)

# Sort strings by length
words = ['python', 'is', 'awesome']
sorted_words = sorted(words, key=lambda w: len(w))
print(sorted_words) # ['is', 'python', 'awesome']
When to Use Lambda

Use lambda for simple, one-time operations. For complex logic or reusable functions, use def for better readability.


2. The map() Function

map() applies a function to every item in an iterable and returns an iterator.

Syntax

map(function, iterable)

Examples

# Square all numbers
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared) # [1, 4, 9, 16, 25]

# Convert strings to integers
str_nums = ['1', '2', '3', '4']
int_nums = list(map(int, str_nums))
print(int_nums) # [1, 2, 3, 4]

# Multiple iterables
a = [1, 2, 3]
b = [10, 20, 30]
result = list(map(lambda x, y: x + y, a, b))
print(result) # [11, 22, 33]

# Using with regular functions
def celsius_to_fahrenheit(c):
return (c * 9/5) + 32

temps_c = [0, 10, 20, 30, 40]
temps_f = list(map(celsius_to_fahrenheit, temps_c))
print(temps_f) # [32.0, 50.0, 68.0, 86.0, 104.0]

Map vs List Comprehension

numbers = [1, 2, 3, 4, 5]

# Using map
squared_map = list(map(lambda x: x**2, numbers))

# Using list comprehension (more Pythonic)
squared_comp = [x**2 for x in numbers]

# Both produce: [1, 4, 9, 16, 25]

3. The filter() Function

filter() creates an iterator containing only items for which the function returns True.

Syntax

filter(function, iterable)

Examples

# 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 positive numbers
values = [-5, -2, 0, 3, 7, -1, 9]
positives = list(filter(lambda x: x > 0, values))
print(positives) # [3, 7, 9]

# Filter strings by length
words = ['hi', 'hello', 'hey', 'goodbye', 'yo']
long_words = list(filter(lambda w: len(w) > 3, words))
print(long_words) # ['hello', 'goodbye']

# Filter None values
data = [1, None, 3, None, 5]
clean_data = list(filter(None, data)) # None as function
print(clean_data) # [1, 3, 5]

Filter vs List Comprehension

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Using filter
evens_filter = list(filter(lambda x: x % 2 == 0, numbers))

# Using list comprehension (more Pythonic)
evens_comp = [x for x in numbers if x % 2 == 0]

# Both produce: [2, 4, 6, 8, 10]

4. The reduce() Function

reduce() applies a function cumulatively to items in an iterable, reducing it to a single value.

Syntax

from functools import reduce

reduce(function, iterable, [initializer])

Examples

from functools import reduce

# Sum of all numbers
numbers = [1, 2, 3, 4, 5]
total = reduce(lambda x, y: x + y, numbers)
print(total) # 15

# Product of all numbers
product = reduce(lambda x, y: x * y, numbers)
print(product) # 120

# Find maximum
numbers = [3, 7, 2, 9, 1]
maximum = reduce(lambda x, y: x if x > y else y, numbers)
print(maximum) # 9

# With initial value
numbers = [1, 2, 3]
result = reduce(lambda x, y: x + y, numbers, 10)
print(result) # 16 (10 + 1 + 2 + 3)

# Concatenate strings
words = ['Hello', ' ', 'World', '!']
sentence = reduce(lambda x, y: x + y, words)
print(sentence) # 'Hello World!'

How reduce() Works

# reduce(lambda x, y: x + y, [1, 2, 3, 4])
# Step 1: x=1, y=2 → result=3
# Step 2: x=3, y=3 → result=6
# Step 3: x=6, y=4 → result=10
# Final result: 10

5. Combining Functional Tools

Chaining Operations

from functools import reduce

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Get sum of squares of even numbers
result = reduce(
lambda x, y: x + y,
map(lambda x: x**2,
filter(lambda x: x % 2 == 0, numbers))
)
print(result) # 220 (4 + 16 + 36 + 64 + 100)

# More readable with list comprehension
result = sum(x**2 for x in numbers if x % 2 == 0)
print(result) # 220

Practical Example: Data Processing Pipeline

# Sample data
sales = [
{'product': 'Laptop', 'price': 1000, 'quantity': 2},
{'product': 'Mouse', 'price': 25, 'quantity': 5},
{'product': 'Keyboard', 'price': 75, 'quantity': 3},
{'product': 'Monitor', 'price': 300, 'quantity': 1}
]

# Calculate total revenue for items over $50
total_revenue = reduce(
lambda acc, sale: acc + sale,
map(lambda s: s['price'] * s['quantity'],
filter(lambda s: s['price'] > 50, sales))
)
print(f"Total revenue: ${total_revenue}") # $2525

6. Higher-Order Functions

Functions that take other functions as arguments or return functions.

Functions as Arguments

def apply_operation(x, y, operation):
"""Apply operation to x and y"""
return operation(x, y)

# Different operations
add = lambda x, y: x + y
multiply = lambda x, y: x * y
power = lambda x, y: x ** y

print(apply_operation(5, 3, add)) # 8
print(apply_operation(5, 3, multiply)) # 15
print(apply_operation(5, 3, power)) # 125

Functions Returning Functions

def make_multiplier(n):
"""Return a function that multiplies by n"""
return lambda x: x * n

# Create specific multipliers
double = make_multiplier(2)
triple = make_multiplier(3)

print(double(5)) # 10
print(triple(5)) # 15

# Create power functions
def make_power(n):
"""Return a function that raises to power n"""
return lambda x: x ** n

square = make_power(2)
cube = make_power(3)

print(square(4)) # 16
print(cube(4)) # 64

7. Function Composition

Combining multiple functions to create new functions.

def compose(*functions):
"""Compose multiple functions"""
def inner(arg):
result = arg
for func in reversed(functions):
result = func(result)
return result
return inner

# Define simple functions
add_five = lambda x: x + 5
multiply_by_two = lambda x: x * 2
square = lambda x: x ** 2

# Compose functions
f = compose(square, multiply_by_two, add_five)
print(f(3)) # ((3 + 5) * 2) ** 2 = 256

# More practical example
def remove_spaces(s): return s.replace(' ', '')
def to_uppercase(s): return s.upper()
def add_prefix(s): return 'PREFIX_' + s

process_string = compose(add_prefix, to_uppercase, remove_spaces)
result = process_string("hello world")
print(result) # 'PREFIX_HELLOWORLD'

8. Partial Functions

Creating new functions by fixing some arguments of an existing function.

from functools import partial

# Regular function
def power(base, exponent):
return base ** exponent

# Create partial functions
square = partial(power, exponent=2)
cube = partial(power, exponent=3)

print(square(5)) # 25
print(cube(5)) # 125

# More practical example
def log_message(message, level='INFO'):
print(f"[{level}] {message}")

# Create specialized logging functions
log_error = partial(log_message, level='ERROR')
log_warning = partial(log_message, level='WARNING')

log_error("Something went wrong!")
log_warning("Proceed with caution")

9. Comparison Table

FunctionPurposeReturnsExample
map()Transform itemsIterator of resultsmap(str.upper, ['a', 'b'])
filter()Select itemsIterator of filtered itemsfilter(lambda x: x > 0, [-1, 2])
reduce()Aggregate to single valueSingle valuereduce(lambda x, y: x+y, [1,2,3])
lambdaCreate anonymous functionFunction objectlambda x: x * 2
partial()Fix function argumentsNew functionpartial(pow, 2)

10. Functional vs Imperative Style

Imperative (Procedural)

numbers = [1, 2, 3, 4, 5]
result = []
for num in numbers:
if num % 2 == 0:
result.append(num ** 2)
total = 0
for num in result:
total += num
print(total)

Functional

from functools import reduce

numbers = [1, 2, 3, 4, 5]
total = reduce(
lambda x, y: x + y,
map(lambda x: x ** 2,
filter(lambda x: x % 2 == 0, numbers))
)
print(total)

Pythonic (Best)

numbers = [1, 2, 3, 4, 5]
total = sum(x**2 for x in numbers if x % 2 == 0)
print(total)
Readability

While functional programming is powerful, prioritize readability. List comprehensions are often more Pythonic than map()/filter().


Summary

✅ Lambda functions create anonymous, one-line functions
map() transforms items in an iterable
filter() selects items based on a condition
reduce() aggregates items to a single value
✅ Higher-order functions enhance code flexibility
✅ Prefer list comprehensions for readability


Next Steps

In Module 17, you'll learn:

  • Regular expressions for pattern matching
  • The re module
  • Common regex patterns
  • Text processing and validation

Practice Exercises

  1. Use map() to convert a list of temperatures from Celsius to Fahrenheit
  2. Use filter() to extract all prime numbers from a list
  3. Use reduce() to find the longest string in a list
  4. Create a function that composes three mathematical operations
  5. Build a data processing pipeline using map(), filter(), and reduce()
Challenge

Create a function pipeline() that:

  • Takes multiple functions as arguments
  • Returns a new function that applies them in sequence
  • Handles both single values and iterables
  • Example: pipeline(double, add_ten, square)(5)(5*2+10)²=400