Introduction π
The functools module provides higher-order functionsβtools that act on or return other functions. It enables memoization, function partial application, ordering, caching, and more. These tools make your Python code cleaner, faster, and more functional.
Note
π‘ Contains powerful decorators like @lru_cache
π‘ Perfect for optimization, callbacks, sorting, pipelines
1. Importing functools π§±
import_functools.py
import functools2. partial() β Pre-Fill Function Arguments π―
partial() allows you to pre-set some arguments of a function, creating a new function.
partial_example.py
import functools
def power(base, exp):
return base ** exp
square = functools.partial(power, exp=2)
cube = functools.partial(power, exp=3)
print(square(5)) # 25
print(cube(4)) # 64β Converts multi-argument functions into simpler ones
β Great for callbacks, mappings, default configurations
3. lru_cache() β Memoization for Speed β‘
@functools.lru_cache caches function results β dramatically speeds up repeated calls.
lru_cache_example.py
import functools
@functools.lru_cache(maxsize=1000)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
print(fib(30))Note
π‘ Makes expensive recursive algorithms extremely fast
4. reduce() β Functional Reduction π
reduce() applies a function cumulatively to items in a sequence.
reduce_example.py
import functools
nums = [1, 2, 3, 4]
total = functools.reduce(lambda a, b: a + b, nums)
print(total) # 10β Useful for sums, products, custom fold operations
5. cmp_to_key() β Custom Sorting Logic π
Converts old-style compare functions into key functions for sorting.
cmp_to_key_example.py
import functools
def compare(a, b):
if a % 10 < b % 10: return -1
if a % 10 > b % 10: return 1
return 0
nums = [12, 25, 33, 47]
sorted_nums = sorted(nums, key=functools.cmp_to_key(compare))
print(sorted_nums)β Enables fine-grained control over sorting behavior
β Great for custom ranking systems
6. singledispatch() β Function Overloading in Python π¦
singledispatch_example.py
from functools import singledispatch
@singledispatch
def process(x):
print("Default:", x)
@process.register(int)
def _(x):
print("Integer:", x)
@process.register(list)
def _(x):
print("List:", x)
process(10)
process([1, 2, 3])
process("Hello")Note
π‘ βFunction overloadingβ in Python
7. wraps() β Preserve Metadata for Decorators π
When writing custom decorators, @wraps preserves function name, docstring, and metadata.
wraps_example.py
import functools
def my_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print("Calling function...")
return func(*args, **kwargs)
return wrapper
@my_decorator
def greet():
"Say hello"
print("Hello!")
print(greet.__name__) # greet
print(greet.__doc__) # Say helloβ Essential when building clean decorators
8. cached_property β Fast Property Caching ποΈ
cached_property_example.py
from functools import cached_property
import time
class Data:
@cached_property
def value(self):
time.sleep(2)
return 100
d = Data()
print(d.value) # slow first time
print(d.value) # instantβ Ideal for expensive calculations
β Result stored after first access
9. total_ordering β Auto-Generate Comparison Methods βοΈ
total_ordering_example.py
from functools import total_ordering
@total_ordering
class Number:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return self.value == other.value
def __lt__(self, other):
return self.value < other.value
n1 = Number(5)
n2 = Number(10)
print(n1 < n2)
print(n1 >= n2)β Only define __eq__ + one comparison method
β Automatically gets: >, <=, >=
10. Practical Example β Rate Limiter β³
rate_limiter.py
import functools, time
def rate_limit(func):
last_called = [0]
@functools.wraps(func)
def wrapper(*args, **kwargs):
if time.time() - last_called[0] < 2:
print("Too fast!")
return
last_called[0] = time.time()
return func(*args, **kwargs)
return wrapper
@rate_limit
def api_call():
print("API call executed")
api_call()
api_call()β Real-world use of decorators + wraps
Functools Cheat Sheet π
| Function | Purpose |
|---|---|
| partial | Pre-fill parameters |
| lru_cache | Memoization/caching |
| reduce | Functional reduction |
| cmp_to_key | Custom sorting logic |
| singledispatch | Function overloading |
| wraps | Decorator metadata preservation |
| cached_property | Property caching |
| total_ordering | Auto-generate comparison operators |
Best Practices π‘
- β Use @lru_cache for expensive functions
- β Use partial() to simplify callbacks & repetitive code
- β Always wrap decorators with @wraps
- β Prefer singledispatch for type-based logic
- β Use total_ordering to reduce boilerplate
Conclusion π
You now fully understand the Functools module! Want the next topic? Try Statistics, Decimal, Pathlib, Shutil, or Subprocess. Just tell me! π