Topic 16 of 64
Collections Module
Overview
Python's collections module provides specialized container datatypes that outperform built-in equivalents for specific use cases — Counter for counting, defaultdict for grouping, deque for queues, and namedtuple for lightweight objects.
Syntax
python
from collections import Counter, defaultdict, deque, namedtuple, OrderedDict
# Counter — frequency counting
words = "the quick brown fox jumps over the lazy dog".split()
counts = Counter(words)
counts["the"] # 2
counts.most_common(3) # [("the", 2), ("quick", 1), ("brown", 1)]
# defaultdict — auto-creates missing keys
groups = defaultdict(list)
for user in users:
groups[user["role"]].append(user["name"])
# groups["admin"] = ["Priya", "Rahul"]
# deque — fast O(1) from both ends
queue = deque(maxlen=100) # circular buffer
queue.appendleft("new item") # O(1)
queue.pop() # O(1)
# namedtuple — immutable, lightweight objects
Point = namedtuple("Point", ["x", "y"])
p = Point(10, 20)
p.x # 10 — named access
p[0] # 10 — index access too
x, y = p # tuple unpacking worksCommon Pitfalls
- Counter arithmetic works: counter1 + counter2 merges counts, counter1 - counter2 subtracts (removes negatives).
- defaultdict(list) is different from defaultdict(lambda: []) — both work but the former is more Pythonic.
- Interview tip: Counter is perfect for frequency analysis — much faster than manually incrementing dict values.
Real-World Example
A log analyzer using Counter and defaultdict:
example
python
from collections import Counter, defaultdict
from datetime import datetime
def analyze_api_logs(log_entries: list[dict]) -> dict:
endpoint_hits = Counter()
error_by_endpoint = defaultdict(list)
hourly_traffic = defaultdict(int)
for entry in log_entries:
endpoint = entry["endpoint"]
status = entry["status_code"]
hour = datetime.fromisoformat(entry["timestamp"]).hour
endpoint_hits[endpoint] += 1
hourly_traffic[hour] += 1
if status >= 500:
error_by_endpoint[endpoint].append({
"status": status,
"time": entry["timestamp"],
"error": entry.get("error", "Unknown")
})
return {
"top_endpoints": endpoint_hits.most_common(10),
"peak_hour": max(hourly_traffic, key=hourly_traffic.get),
"error_prone": {
k: len(v) for k, v in error_by_endpoint.items()
if len(v) > 5 # more than 5 errors
}
}