Python Collections Module: Counter, defaultdict, deque and namedtuple with Worked Examples
Counter counts values, defaultdict creates missing groups, deque works at both ends, and namedtuple gives fixed records readable fields.
KnowledgeGate Team
Exam prep & CS education

You already know list, tuple and dict, but manual counting, grouping and queue code can still make a simple program noisy. Specialised collections containers reduce that boilerplate. Their edge cases include missing keys, non-positive counts, bounded eviction and immutable records, so they complement the built-ins rather than replace them.
For built-in str, list, tuple, set and dict, plus a worked word counter, use Python Collections and Strings: Complete Guide with a Worked Word Counter. Python programming course connects collections to file paths, CSV, dates, statistics and JSON. The collections module itself handles narrower container jobs: counting, missing-key factories, two-ended queues, named records, layered mappings and explicit reordering.
Python collections module: choose the container from the operation
The collections module packages containers for recurring data-structure operations. Import names explicitly so each dependency and container choice remains visible:
from collections import Counter, defaultdict, deque, namedtuple, ChainMap, OrderedDictAvoid from collections import *. Explicit imports make both intent and dependencies clearer.
Operation you need | Container |
|---|---|
Count frequencies |
|
Initialise missing keys or group values |
|
Add or remove items at either end |
|
Create a lightweight named record |
|
Search layered mappings |
|
Reorder keys explicitly |
|
UserDict, UserList and UserString wrap built-in container behaviour for subclasses that need controlled overrides. Use them when a custom container benefits from delegation to an underlying data object. These wrapper bases connect Python syntax to practical Coding & DSA work.
Counter in Python: count, query, update and subtract
Counter counts hashable values and returns zero for a missing item:
orders = ["pen", "book", "pen", "pencil", "book", "pen", "eraser"]
counts = Counter(orders)
print(dict(counts)) # {'pen': 3, 'book': 2, 'pencil': 1, 'eraser': 1}
counts["pen"] # 3
counts["marker"] # 0
counts.most_common(2) # [('pen', 3), ('book', 2)]Now subtract stock adjustments from the same object:
counts.subtract({"pen": 1, "book": 2, "eraser": 2})
print(dict(counts)) # {'pen': 2, 'book': 0, 'pencil': 1, 'eraser': -1}
print(+counts) # Counter({'pen': 2, 'pencil': 1})Subtraction retains zero and negative counts. Unary plus creates a new Counter containing only positive counts. Counter keys use normal dictionary hashing, and a missing key still reads as zero.

defaultdict in Python: group values without repeated key checks
With a plain dictionary, packages[city].append(tracking_id) raises KeyError when city is new. A defaultdict calls its factory to create the missing list:
shipments = [("Delhi", "PK-104"), ("Pune", "PK-105"),
("Delhi", "PK-106"), ("Kochi", "PK-107"),
("Pune", "PK-108")]
packages = defaultdict(list)
for city, tracking_id in shipments:
packages[city].append(tracking_id)
print(dict(packages))
# {'Delhi': ['PK-104', 'PK-106'], 'Pune': ['PK-105', 'PK-108'], 'Kochi': ['PK-107']}The grouping is deterministic: Delhi receives ['PK-104', 'PK-106'], Pune receives ['PK-105', 'PK-108'], and Kochi receives ['PK-107']. Keys retain their first-insertion order in the displayed dictionary.
Pass the callable as defaultdict(list), not defaultdict(list()). The latter passes an already-created list and raises TypeError. Reading packages["Jaipur"] returns [], but it also stores "Jaipur": [] in the mapping.
deque in Python: queues, bounded history and sliding windows
A deque supports append and pop at the right, plus appendleft and popleft at the left. A queue consumes its oldest item with popleft(), matching FIFO queue behaviour.
For a size-3 moving average over [4, 8, 6, 10, 12]:
Window
[4, 8, 6]: sum4 + 8 + 6 = 18, average18 / 3 = 6.0.Remove
4, append10: window[8, 6, 10], sum8 + 6 + 10 = 24, average24 / 3 = 8.0.Remove
8, append12: window[6, 10, 12], sum6 + 10 + 12 = 28, average28 / 3 = 9.333..., rounded to9.33.
The exact result list is [6.0, 8.0, 9.33].

A bounded deque evicts automatically. After history = deque(["T1", "T2", "T3"], maxlen=3) and history.append("T4"), "T1" disappears and the result is deque(['T2', 'T3', 'T4'], maxlen=3). Make automatic eviction explicit when silent item loss would be a bug.
namedtuple, ChainMap and OrderedDict: records and mapping layers
A named tuple gives tuple values readable field names:
from math import sqrt
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
x, y = p
distance = sqrt(3**2 + 4**2) # sqrt(9 + 16) = sqrt(25) = 5.0
q = p._replace(x=6)Here p.x == 3, unpacking gives x == 3 and y == 4, and q == Point(x=6, y=4). The original remains Point(x=3, y=4) because named tuples are immutable.
ChainMap searches mappings from first to last:
defaults = {"theme": "light", "page_size": 20}
user = {"theme": "dark"}
settings = ChainMap(user, defaults)Now settings["theme"] == "dark" and settings["page_size"] == 20. Assigning settings["page_size"] = 50 writes to the first mapping. user becomes {"theme": "dark", "page_size": 50}, while defaults is unchanged.
Start an OrderedDict with [('compile', 2), ('test', 3), ('deploy', 1)]. After move_to_end("compile"), its key order is test, deploy, compile; popitem(last=False) then returns ('test', 3). Ordinary dictionaries preserve insertion order, so choose OrderedDict when explicit reordering, oldest-item removal or order-sensitive equality carries the logic.
Python collections mistakes: factories, mutation and access patterns
Match each failure to its repair:
defaultdict(list())passes a list, not a callable. Usedefaultdict(list).p.x = 6fails because a named tuple is immutable. Usep._replace(x=6).Counter.elements()omits zero and negative counts. Inspectitems()when those states matter.ChainMapassignment writes only to its first mapping. Mutate the intended underlying mapping explicitly.Frequent middle indexing is a poor
dequeaccess pattern. Use a list when random access dominates.
Bounded capacity is another trap. Given deque([1, 2, 3], maxlen=3), appendleft(0) silently removes 3 and produces deque([0, 1, 2], maxlen=3). Make automatic eviction explicit whenever losing an item could surprise the reader.
The choice checklist is therefore operational: count, group, process ends, model a record, layer settings or reorder keys.
Python collections exercises: predict the exact result
Counter:
letters = Counter("mississippi")givesm: 1,i: 4,s: 4,p: 2.letters.most_common(2) == [('i', 4), ('s', 4)]. Equal counts retain first-encounter order here, andiappears befores.Deque: start with
d = deque([10, 20, 30], maxlen=3). Afterd.appendleft(5), the state is[5, 10, 20]because30is evicted from the right. Afterd.rotate(1), the final state is[20, 5, 10].Defaultdict: use
defaultdict(set)to group[('red', 'A'), ('blue', 'B'), ('red', 'C'), ('blue', 'B')]. The logical result isred -> {'A', 'C'}andblue -> {'B'}. Repeating('blue', 'B')does not duplicateBin a set.
Coding quizzes and interviews commonly test output prediction, factory selection, mutation and edge cases.
Python collections module: the short version and next step
Container | Core job |
|---|---|
| Count values |
| Initialise missing values and group items |
| Work efficiently at both ends |
| Store immutable named fields |
| Search mapping layers |
| Perform explicit order operations |
Choose the container from the operation, then test its edge case: missing keys, non-positive counts, immutability or bounded eviction. Continue with the Python course for a complete language path. If your immediate goal is implementing data structures and solving problems, follow DSA Using Python instead.
Keep learning
JSON and CSV in Python: Read, Write and Convert Data with Worked Examples
Use Python's standard library to read, update, write and convert JSON and CSV safely. The examples trace types, quoting, calculations and validation.
Date and Time in Python: datetime Tutorial with Parsing, Arithmetic and Time Zones
Build reliable Python date-time values from input text, calculate across midnight, and convert one instant between Asia/Kolkata and UTC.
Python for GATE: DA Syllabus, Observed Weightage and Prep Order
Settle the DA-versus-CS language question, see what one official DA paper contained, and build Python, data structures and algorithms in the right sequence.
Type Hints in Python: Functions, Collections and Checked Examples
Learn what Python type hints do, how to annotate common data shapes, and how a checker catches mistakes through exact, runnable examples.





