Functional Programming
functools Module
The functools standard library — partial application, reduce, lru_cache memoization, singledispatch, and wraps for building composable functional utilities.
Interview: reduce, partial, and lru_cache are common interview topics — shows mastery of Python functional tools.
The functools module provides higher-order functions and tools for working with callable objects. Key functions include partial (partial application), reduce (fold), lru_cache (memoization), singledispatch (type-based dispatch), and wraps (preserving function metadata).
Key Functions
partial(func, *args)— freeze some arguments, returns a new callablereduce(func, iterable)— apply function cumulatively to reduce to single value@lru_cache(maxsize)— memoize function results for performance@singledispatch— dispatch to different implementations based on type@wraps(func)— preserve function name, docstring, and annotations
reduce (Fold)
reduce(lambda a, b: a + b, [1,2,3])→ 6 (sum)- Takes a binary function and applies it left-to-right across the iterable
- Optional
initializerparameter acts as default/seed value - Often a simple loop or sum()/max()/min() is more readable
lru_cache (Memoization)
- Caches return values based on function arguments
maxsize=128limits cache size (LRU eviction),maxsize=Noneis unbounded- Dramatically speeds up recursive functions and expensive computations
- Only works with hashable arguments (no lists or dicts)
Interview Insight
Know when to use reduce vs a simple loop. lru_cache is the go-to solution for memoization in interviews (Fibonacci, dynamic programming). partial is useful for callback configuration.
Use Cases
Memoization — caching expensive computations with lru_cache
Callback configuration — partial to pre-fill arguments for event handlers
Data aggregation — reduce for custom folding operations
Type dispatch — singledispatch for polymorphic behavior without classes
Decorator writing — wraps to maintain function identity in decorators
Common Mistakes
Using reduce when sum()/max()/min() would be clearer and more Pythonic
Forgetting lru_cache only works with hashable arguments — no lists or dicts
Not setting maxsize on lru_cache for unbounded data — memory grows forever
Forgetting @wraps in decorators — breaks __name__, __doc__, and introspection
Using partial for everything when a lambda or nested function is clearer