When I started maintaining a legacy Python codebase, the hardest part wasn't understanding the business logic — it was reading the same 50-line pattern scattered across 12 modules.
Then I discovered functools — not just lru_cache, but the deeper tools that change how you structure code.
1. @singledispatch
Replace isinstance chains with clean type dispatch:
from functools import singledispatch
@singledispatch
def format_data(data):
return str(data)
@format_data.register(dict)
def _(data):
return json.dumps(data, indent=2)
@format_data.register(list)
def _(data):
return '\n'.join(str(x) for x in data)
2. @total_ordering
Define __eq__ and one comparison, get all six for free:
from functools import total_ordering
@total_ordering
class Priority:
def __init__(self, level):
self.level = level
def __eq__(self, other):
return self.level == other.level
def __lt__(self, other):
return self.level < other.level
assert Priority(3) >= Priority(2)
assert Priority(1) <= Priority(2)
3. @wraps
Never lose __name__ or __doc__ in your decorators:
from functools import wraps
def log_call(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
@log_call
def process_payment(amount):
"""Process a payment transaction."""
return f"Processed ${amount}"
print(process_payment.__name__) # 'process_payment'
print(process_payment.__doc__) # 'Process a payment transaction.'
4. @lru_cache
Use cache_info() to monitor your memoization:
from functools import lru_cache
import time
@lru_cache(maxsize=128)
def fetch_user_permissions(user_id):
time.sleep(1) # Simulate DB
return {"can_read": True, "can_write": False}
print(fetch_user_permissions.cache_info())
# CacheInfo(hits=0, misses=1, maxsize=128, currsize=1)
5. partial
Replace one-off factory classes with a single call:
from functools import partial
def create_api_client(base_url, api_key, timeout=30, retries=3):
return {"base_url": base_url, "key": api_key[-4:], "timeout": timeout}
prod_client = partial(create_api_client, "https://api.prod.com", timeout=60)
dev_client = partial(create_api_client, "https://api.dev.local", timeout=5)
I've been collecting these patterns into reference templates. The Prompt Creator Bundle — Developer Edition includes prompt templates for generating Python code with these patterns applied correctly.
Top comments (0)