Python's collections module provides a set of high-performance, specialized container datatypes that extend the built-in data structures like list, tuple, and dict. They help write cleaner, more readable, and often faster code.
In this topic, we focus on: namedtuple, deque, Counter, defaultdict, OrderedDict, and ChainMap.
KeyError.namedtuple(typename, field_names) creates a new tuple subclass with named fields. You can access elements using dot notation instead of numeric indexes.
Common use-cases: representing simple records like points, database rows, or configuration values.
deque(iterable, maxlen=None) creates a double-ended queue. It supports operations like append, appendleft, pop, and popleft in O(1) time.
Ideal for queues, BFS, sliding windows, and scenarios with heavy pushing/popping at both ends.
Counter(iterable) counts occurrences of elements and stores them in a dictionary-like object where keys are elements and values are their counts.
Useful for frequency analysis (e.g., most common words, characters, or items).
defaultdict(default_factory) automatically creates default values for missing keys using default_factory (like int, list, or dict).
This avoids repetitive existence checks and KeyError exceptions.
OrderedDict() acts like a normal dictionary but remembers the insertion order of keys. In modern Python (3.7+), normal dicts also preserve insertion order, but OrderedDict still provides extra methods like move_to_end.
ChainMap(*maps) groups multiple mappings into a single view. When you access a key, it searches each mapping in order until it finds it.
Useful for layering configurations (e.g., defaults, env overrides, CLI args).
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y) # Access via field names
from collections import deque
dq = deque([1, 2, 3])
dq.appendleft(0) # [0, 1, 2, 3]
dq.append(4) # [0, 1, 2, 3, 4]
dq.pop() # removes 4 → [0, 1, 2, 3]
dq.popleft() # removes 0 → [1, 2, 3]
print(dq)
from collections import Counter
data = ['a', 'b', 'c', 'a', 'b', 'a']
count = Counter(data)
print(count) # Counter({'a': 3, 'b': 2, 'c': 1})
print(count['a']) # 3
print(count.most_common(1)) # [('a', 3)]
from collections import defaultdict
d = defaultdict(int) # default value 0 for missing keys
d['a'] += 1
d['b'] += 2
print(d) # defaultdict(<class 'int'>, {'a': 1, 'b': 2})
print(d['c']) # 0 (auto-created, no KeyError)
from collections import OrderedDict
od = OrderedDict()
od['a'] = 1
od['b'] = 2
od['c'] = 3
print(od) # Maintains insertion order
od.move_to_end('a')
print(od) # 'a' moved to the end
from collections import ChainMap
defaults = {'theme': 'light', 'page_size': 10}
env = {'page_size': 20}
user = {'theme': 'dark'}
settings = ChainMap(user, env, defaults)
print(settings['theme']) # 'dark' (from user)
print(settings['page_size']) # 20 (from env)
print(p.x, p.y) → 10 20dq becomes deque([1, 2, 3]).Counter({'a': 3, 'b': 2, 'c': 1}) plus handy methods like most_common().'c' return 0 instead of raising KeyError.move_to_end().Counter whenever you need frequency counts instead of manually building dictionaries.deque over lists for queue/stack patterns with heavy front operations.defaultdict(list) or defaultdict(int) to simplify aggregation logic.dict preserves insertion order, but use OrderedDict if you need its extra methods or explicit ordering semantics.ChainMap to layer configuration sources instead of manually merging dictionaries.Counter from a string and print the three most common characters using most_common(3).deque to implement a simple queue with enqueue (append) and dequeue (popleft). Test it with several elements.defaultdict(list) and group student names by their grade (e.g., keys as grades, values as lists of names).ChainMap: defaults, environment variables, and user settings. Print which layer each setting came from.OrderedDict and the move_to_end() method to reorder menu items in a CLI app.