Difficulty: Intermediate
What useful data structures does the collections module provide?
The collections module provides specialized container types that extend Python's built-in dict, list, set, and tuple.
Key classes: - Counter: dict subclass for counting hashable objects - defaultdict: dict with a factory for missing keys - deque: double-ended queue with O(1) append/pop from both ends - namedtuple: tuple subclass with named fields - OrderedDict: dict that remembers insertion order (relevant pre-3.7) - ChainMap: groups multiple dicts into a single view
These are often the right answer to interview coding problems because they simplify common patterns.
from collections import deque
# deque vs list for queue operations
d = deque([1, 2, 3])
d.append(4) # Right end: [1, 2, 3, 4]
d.appendleft(0) # Left end: [0, 1, 2, 3, 4]
d.pop() # Right: 4, deque is [0, 1, 2, 3]
d.popleft() # Left: 0, deque is [1, 2, 3]
print(d)
# Rotation
d = deque([1, 2, 3, 4, 5])
d.rotate(2) # Rotate right by 2
print(d) # deque([4, 5, 1, 2, 3])
d.rotate(-2) # Rotate left by 2
print(d) # deque([1, 2, 3, 4, 5])
# Fixed-size deque (sliding window)
recent = deque(maxlen=3)
for i in range(5):
recent.append(i)
print(f"Added {i}: {list(recent)}")
# Performance: deque vs list
import time
n = 100_000
lst = []
start = time.time()
for i in range(n):
lst.insert(0, i) # O(n) each time!
print(f"List insert(0): {time.time() - start:.4f}s")
d = deque()
start = time.time()
for i in range(n):
d.appendleft(i) # O(1) each time
print(f"Deque appendleft: {time.time() - start:.4f}s")
deque provides O(1) operations on both ends, while list.insert(0) is O(n). maxlen creates a sliding window that automatically drops old items.
from collections import Counter
# Count anything hashable
words = 'the quick brown fox jumps over the lazy dog the fox'.split()
word_count = Counter(words)
print(word_count)
print(word_count.most_common(3)) # Top 3
# Counter arithmetic
inventory_a = Counter(apples=3, oranges=2, bananas=5)
inventory_b = Counter(apples=1, oranges=4, grapes=3)
print(inventory_a + inventory_b) # Add counts
print(inventory_a - inventory_b) # Subtract (drops zero/negative)
print(inventory_a & inventory_b) # Minimum of each
print(inventory_a | inventory_b) # Maximum of each
# Practical: find most common character
def most_common_char(s):
counter = Counter(s.lower().replace(' ', ''))
return counter.most_common(1)[0]
char, count = most_common_char("Hello World")
print(f"Most common: '{char}' ({count} times)")
# Check if one is subset of another (anagram check)
def is_anagram(s1, s2):
return Counter(s1.lower().replace(' ', '')) == Counter(s2.lower().replace(' ', ''))
print(is_anagram('listen', 'silent')) # True
Counter is invaluable for interview problems: frequency counting, anagram checking, top-k problems, and inventory management.
from collections import namedtuple, ChainMap
# namedtuple: lightweight, immutable class
Point = namedtuple('Point', ['x', 'y'])
p = Point(3, 4)
print(p.x, p.y) # 3 4 (access by name)
print(p[0], p[1]) # 3 4 (access by index)
x, y = p # Unpacking works
print(f"({x}, {y})")
# Convert to dict
print(p._asdict()) # {'x': 3, 'y': 4}
# Create from dict
data = {'x': 10, 'y': 20}
p2 = Point(data)
print(p2) # Point(x=10, y=20)
# namedtuple with defaults (Python 3.6.1+)
Config = namedtuple('Config', ['host', 'port', 'debug'], defaults=['localhost', 8080, False])
print(Config()) # Config(host='localhost', port=8080, debug=False)
print(Config('0.0.0.0')) # Config(host='0.0.0.0', port=8080, debug=False)
# ChainMap: layered dict lookup
defaults = {'color': 'blue', 'size': 'medium', 'font': 'Arial'}
user_prefs = {'color': 'red'}
env_overrides = {'size': 'large'}
config = ChainMap(env_overrides, user_prefs, defaults)
print(config['color']) # 'red' (from user_prefs)
print(config['size']) # 'large' (from env_overrides)
print(config['font']) # 'Arial' (from defaults)
namedtuple creates readable, immutable records. ChainMap provides a layered lookup - first dict found wins. Both are used extensively in production code.
Counter, defaultdict, deque, namedtuple, OrderedDict, ChainMap