Caching & Memoization
Dictionaries are perfect for caching expensive computations. Store results with input as key.
# Simple memoization cache
def fibonacci_cached():
cache = {}
def fib(n):
if n in cache:
return cache[n]
if n <= 1:
result = n
else:
result = fib(n - 1) + fib(n - 2)
cache[n] = result
return result
return fib
fib = fibonacci_cached()
print(fib(100)) # Instant! Without cache would take forever
# Using functools.lru_cache (recommended)
from functools import lru_cache
@lru_cache(maxsize=128)
def expensive_api_call(user_id):
# Simulated expensive operation
return f"Data for user {user_id}"
# LRU cache with TTL (time-to-live)
import time
class TTLCache:
def __init__(self, ttl_seconds=60):
self.cache = {}
self.ttl = ttl_seconds
def get(self, key):
if key in self.cache:
value, timestamp = self.cache[key]
if time.time() - timestamp < self.ttl:
return value
del self.cache[key]
return None
def set(self, key, value):
self.cache[key] = (value, time.time())
# Usage
cache = TTLCache(ttl_seconds=300) # 5 minute TTL
cache.set('api_result', {'data': [1, 2, 3]})
result = cache.get('api_result')Configuration Management
Dictionaries are ideal for storing application settings with sensible defaults.
# Layered configuration with defaults
DEFAULT_CONFIG = {
'debug': False,
'log_level': 'INFO',
'database': {
'host': 'localhost',
'port': 5432,
'pool_size': 5
},
'cache': {
'enabled': True,
'ttl': 3600
}
}
def load_config(user_config=None, env_config=None):
"""Merge configurations with priority: env > user > default"""
config = DEFAULT_CONFIG.copy()
def deep_merge(base, override):
result = base.copy()
for key, value in override.items():
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
result[key] = deep_merge(result[key], value)
else:
result[key] = value
return result
if user_config:
config = deep_merge(config, user_config)
if env_config:
config = deep_merge(config, env_config)
return config
# Usage
user_settings = {'debug': True, 'database': {'host': 'prod.db.com'}}
final_config = load_config(user_config=user_settings)
# debug=True, database.host='prod.db.com', everything else from defaultsCounting & Frequency Analysis
from collections import Counter
# Word frequency in text
def analyze_text(text):
words = text.lower().split()
word_freq = Counter(words)
return {
'total_words': len(words),
'unique_words': len(word_freq),
'most_common': word_freq.most_common(5),
'word_frequencies': dict(word_freq)
}
# Log analysis - count error types
error_logs = [
{'type': 'ConnectionError', 'service': 'api'},
{'type': 'TimeoutError', 'service': 'database'},
{'type': 'ConnectionError', 'service': 'api'},
{'type': 'ValueError', 'service': 'parser'},
]
error_counts = Counter(log['type'] for log in error_logs)
print(error_counts) # Counter({'ConnectionError': 2, 'TimeoutError': 1, 'ValueError': 1})
# Count by multiple fields
from collections import defaultdict
def count_by_fields(logs, *fields):
counts = defaultdict(int)
for log in logs:
key = tuple(log.get(f) for f in fields)
counts[key] += 1
return dict(counts)
print(count_by_fields(error_logs, 'type', 'service'))
# {('ConnectionError', 'api'): 2, ('TimeoutError', 'database'): 1, ...}Grouping Data
from collections import defaultdict
# Group users by role
users = [
{'name': 'Alice', 'role': 'admin', 'department': 'IT'},
{'name': 'Bob', 'role': 'user', 'department': 'Sales'},
{'name': 'Charlie', 'role': 'admin', 'department': 'IT'},
{'name': 'Diana', 'role': 'user', 'department': 'IT'},
]
# Group by single field
def group_by(items, key):
groups = defaultdict(list)
for item in items:
groups[item[key]].append(item)
return dict(groups)
by_role = group_by(users, 'role')
# {'admin': [Alice, Charlie], 'user': [Bob, Diana]}
# Group by multiple fields
def group_by_multiple(items, *keys):
groups = defaultdict(list)
for item in items:
group_key = tuple(item[k] for k in keys)
groups[group_key].append(item)
return dict(groups)
by_role_dept = group_by_multiple(users, 'role', 'department')
# {('admin', 'IT'): [Alice, Charlie], ('user', 'Sales'): [Bob], ...}
# Using itertools.groupby (requires sorted data)
from itertools import groupby
sorted_users = sorted(users, key=lambda x: x['role'])
for role, group in groupby(sorted_users, key=lambda x: x['role']):
print(f"{role}: {[u['name'] for u in group]}")Lookup Tables
# HTTP status codes
HTTP_STATUS = {
200: 'OK',
201: 'Created',
400: 'Bad Request',
401: 'Unauthorized',
403: 'Forbidden',
404: 'Not Found',
500: 'Internal Server Error',
}
def get_status_message(code):
return HTTP_STATUS.get(code, 'Unknown Status')
# State/country codes
US_STATES = {
'CA': 'California',
'NY': 'New York',
'TX': 'Texas',
# ... more states
}
# Command dispatcher pattern
def handle_create(data):
return f"Creating: {data}"
def handle_update(data):
return f"Updating: {data}"
def handle_delete(data):
return f"Deleting: {data}"
COMMAND_HANDLERS = {
'create': handle_create,
'update': handle_update,
'delete': handle_delete,
}
def dispatch_command(command, data):
handler = COMMAND_HANDLERS.get(command)
if handler:
return handler(data)
raise ValueError(f"Unknown command: {command}")
# Usage
result = dispatch_command('create', {'name': 'Test'})
print(result) # "Creating: {'name': 'Test'}"State Machines
# Order state machine
ORDER_TRANSITIONS = {
'pending': ['confirmed', 'cancelled'],
'confirmed': ['processing', 'cancelled'],
'processing': ['shipped', 'cancelled'],
'shipped': ['delivered', 'returned'],
'delivered': ['returned'],
'cancelled': [],
'returned': [],
}
class Order:
def __init__(self, order_id):
self.order_id = order_id
self.state = 'pending'
self.history = [('pending', None)]
def transition(self, new_state):
valid_transitions = ORDER_TRANSITIONS.get(self.state, [])
if new_state not in valid_transitions:
raise ValueError(
f"Cannot transition from {self.state} to {new_state}. "
f"Valid: {valid_transitions}"
)
self.history.append((new_state, self.state))
self.state = new_state
return self
def can_transition_to(self, state):
return state in ORDER_TRANSITIONS.get(self.state, [])
# Usage
order = Order('ORD-001')
order.transition('confirmed')
order.transition('processing')
order.transition('shipped')
print(order.state) # 'shipped'
print(order.can_transition_to('cancelled')) # FalseGraph Representation
from collections import defaultdict, deque
# Adjacency list representation
class Graph:
def __init__(self):
self.edges = defaultdict(list)
def add_edge(self, from_node, to_node, weight=1):
self.edges[from_node].append((to_node, weight))
def get_neighbors(self, node):
return self.edges[node]
def bfs(self, start):
"""Breadth-first search"""
visited = set()
queue = deque([start])
order = []
while queue:
node = queue.popleft()
if node not in visited:
visited.add(node)
order.append(node)
for neighbor, _ in self.edges[node]:
if neighbor not in visited:
queue.append(neighbor)
return order
def shortest_path(self, start, end):
"""BFS-based shortest path"""
visited = {start}
queue = deque([(start, [start])])
while queue:
node, path = queue.popleft()
if node == end:
return path
for neighbor, _ in self.edges[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append((neighbor, path + [neighbor]))
return None # No path found
# Usage
g = Graph()
g.add_edge('A', 'B')
g.add_edge('A', 'C')
g.add_edge('B', 'D')
g.add_edge('C', 'D')
g.add_edge('D', 'E')
print(g.bfs('A')) # ['A', 'B', 'C', 'D', 'E']
print(g.shortest_path('A', 'E')) # ['A', 'B', 'D', 'E']Data Transformation
# Transform list of dicts to different formats
users = [
{'id': 1, 'name': 'Alice', 'email': '[email protected]'},
{'id': 2, 'name': 'Bob', 'email': '[email protected]'},
{'id': 3, 'name': 'Charlie', 'email': '[email protected]'},
]
# Create lookup by ID
users_by_id = {user['id']: user for user in users}
print(users_by_id[2]) # {'id': 2, 'name': 'Bob', ...}
# Create lookup by email
users_by_email = {user['email']: user for user in users}
# Extract specific fields
emails = {user['id']: user['email'] for user in users}
# {1: '[email protected]', 2: '[email protected]', ...}
# Rename keys
def rename_keys(data, mapping):
"""Rename dictionary keys based on mapping"""
return {mapping.get(k, k): v for k, v in data.items()}
key_mapping = {'id': 'user_id', 'name': 'full_name'}
renamed = [rename_keys(user, key_mapping) for user in users]
# [{'user_id': 1, 'full_name': 'Alice', 'email': ...}, ...]
# Flatten nested structure
nested = {
'user': {
'profile': {
'name': 'Alice',
'settings': {'theme': 'dark'}
}
}
}
def flatten_dict(d, parent_key='', sep='.'):
items = []
for k, v in d.items():
new_key = f"{parent_key}{sep}{k}" if parent_key else k
if isinstance(v, dict):
items.extend(flatten_dict(v, new_key, sep).items())
else:
items.append((new_key, v))
return dict(items)
flat = flatten_dict(nested)
# {'user.profile.name': 'Alice', 'user.profile.settings.theme': 'dark'}On This Page
- Caching & Memoization
- Configuration Management
- Counting & Frequency
- Grouping Data
- Lookup Tables
- State Machines
- Graph Representation
- Data Transformation
Related Content
- JSON & Dictionaries
Converting between JSON and Python dicts
- Advanced Techniques
Explore defaultdict, Counter, and OrderedDict
- Best Practices
Coding standards for effective dictionary usage