Phase 4 · Intermediate PythonModule 23~34 min read

Functional Programming

Treat functions as data with map/filter/reduce, closures, and functools.

What you'll learn

In Python, functions are first-class objects — you can store them, pass them, and return them like any value. That unlocks a powerful, expressive style: functional programming. It's the foundation for decorators (next module) and for clean data transformations.

By the end you'll be able to:

  • Treat functions as first-class objects
  • Write higher-order functions
  • Use map, filter, and reduce
  • Understand closures and reach for functools

Functions as objects

A function is a value. You can assign it to a variable, put it in a list or dict, and pass it around — without calling it (no parentheses). This is the idea everything else in this module builds on:

first_class.py
def shout(text):
    return text.upper() + "!"

greet = shout                # assign a function to a variable
print(greet("hi"))

funcs = [str.upper, str.lower, str.title]   # functions in a list
for f in funcs:
    print(f("Hello World"))

Higher-order functions

A higher-order function takes a function as an argument, returns one, or both. This lets you parameterize behavior, not just data — the caller decides what happens:

hof.py
def apply_twice(func, value):     # takes a function as an argument
    return func(func(value))

def add_three(x):
    return x + 3

print(apply_twice(add_three, 10))     # 10 -> 13 -> 16
print(apply_twice(lambda s: s + "!", "hi"))

map, filter & reduce

The classic functional trio transforms sequences. map applies a function to every item, filter keeps items matching a predicate, and reduce (from functools) folds a sequence into a single value:

mfr.py
from functools import reduce

nums = [1, 2, 3, 4, 5, 6]

evens = list(filter(lambda n: n % 2 == 0, nums))
squared = list(map(lambda n: n * n, nums))
total = reduce(lambda acc, n: acc + n, nums, 0)

print(evens)
print(squared)
print(total)

# Often a comprehension is clearer than map/filter:
print([n * n for n in nums if n % 2 == 0])

Tip

In Python, a comprehension is often clearer than map/filter with a lambda — compare the last line above. Reach for map/filter mainly when you already have a named function to apply; otherwise a comprehension usually reads better.

Closures

When an inner function remembers variables from the enclosing function even after that function has returned, it's a closure. It "closes over" those values — a clean way to build specialized functions and the mechanism behind decorators:

closures.py
def make_multiplier(factor):       # 'factor' is captured by the inner function
    def multiply(x):
        return x * factor          # closure remembers factor
    return multiply

double = make_multiplier(2)
triple = make_multiplier(3)
print(double(10))      # 20
print(triple(10))      # 30

Key idea

double and triple are the same inner function, but each carries its own captured factor. Closures let a function bundle together some remembered state with its behavior — without needing a class.

functools

The functools module is a treasure chest. partial pre-fills some arguments to make a specialized version of a function; lru_cache memoizes results so repeated calls are instant; and wraps (next module) preserves metadata on wrapped functions:

functools_demo.py
from functools import partial, lru_cache

# partial: pre-fill some arguments
def power(base, exp):
    return base ** exp
square = partial(power, exp=2)
print(square(5))       # 25

# lru_cache: memoize expensive calls automatically
@lru_cache
def fib(n):
    return n if n < 2 else fib(n - 1) + fib(n - 2)
print(fib(30))         # fast, thanks to caching

Recap & quick check

Key takeaways

  • Functions are first-class objects: assign, store, and pass them without calling them.
  • Higher-order functions take and/or return functions, parameterizing behavior.
  • map applies a function to each item, filter keeps matches, functools.reduce folds to one value.
  • A closure is an inner function that remembers variables from its enclosing scope.
  • functools helps: partial pre-fills arguments, lru_cache memoizes results.

Quick check

1. What does 'functions are first-class objects' mean?

2. A higher-order function is one that…

3. What does map(f, seq) do?

4. What is a closure?

5. What does functools.lru_cache do?

Closures and higher-order functions lead directly to one of Python's most beloved features. Next up: Module 24 — Decorators.