Python Collections Module
The collections module adds specialised containers that solve common problems in one line: counting items, grouping values, building fast queues and giving names to tuple fields. Interview questions love them.
- Count anything with Counter
- Group values with defaultdict
- Build queues with deque
- Name tuple fields with namedtuple
Counter: count items
Counter takes any iterable and counts how many times each item appears.
from collections import Counter words = "the cat and the hat and the bat".split()counts = Counter(words)print(counts)print(counts["the"], counts["dog"]) # missing items count as 0print(counts.most_common(2))Counter({'the': 3, 'and': 2, 'cat': 1, 'hat': 1, 'bat': 1})
3 0
[('the', 3), ('and', 2)]Counting characters, and doing arithmetic with counters:
from collections import Counter print(Counter("mississippi").most_common(3)) week1 = Counter(passed=40, failed=5)week2 = Counter(passed=42, failed=2, skipped=1)print(week1 + week2)print(sorted((week1 + week2).elements())[:3])[('i', 4), ('s', 4), ('p', 2)]
Counter({'passed': 82, 'failed': 7, 'skipped': 1})
['failed', 'failed', 'failed']Two words are anagrams if their letter counts are equal:
from collections import Counterprint(Counter("listen") == Counter("silent"), Counter("apple") == Counter("paple"))True True
defaultdict: no more KeyError
A defaultdict creates a default value the first time a missing key is used. Pass the type of the default: list, int, set…
from collections import defaultdict employees = [("qa", "Asha"), ("dev", "Ravi"), ("qa", "Meena"), ("ops", "John")] teams = defaultdict(list)for team, name in employees: teams[team].append(name) # no need to check if the key exists print(dict(teams)) letters = defaultdict(int)for ch in "banana": letters[ch] += 1print(dict(letters)){'qa': ['Asha', 'Meena'], 'dev': ['Ravi'], 'ops': ['John']}
{'b': 1, 'a': 3, 'n': 2}deque: a fast queue
A deque (“deck”) adds and removes items quickly at both ends. Removing from the front of a list is slow for big lists; a deque does it instantly.
from collections import deque queue = deque(["task1", "task2"])queue.append("task3") # join at the backqueue.appendleft("urgent") # jump the queueprint(queue) print(queue.popleft()) # serve from the frontprint(queue.pop()) # remove from the backprint(queue)deque(['urgent', 'task1', 'task2', 'task3']) urgent task3 deque(['task1', 'task2'])
maxlen keeps only the last N items, perfect for “recent history”:
from collections import deque recent = deque(maxlen=3)for page in ["home", "search", "product", "cart", "checkout"]: recent.append(page)print(list(recent)) d = deque([1, 2, 3, 4, 5])d.rotate(2)print(d)['product', 'cart', 'checkout'] deque([4, 5, 1, 2, 3])
namedtuple: tuples with field names
from collections import namedtuple Employee = namedtuple("Employee", ["name", "dept", "salary"])e = Employee("Asha", "QA", 52000) print(e)print(e.name, e.salary)print(e._asdict())print(e._replace(salary=56000))Employee(name='Asha', dept='QA', salary=52000)
Asha 52000
{'name': 'Asha', 'dept': 'QA', 'salary': 52000}
Employee(name='Asha', dept='QA', salary=56000)OrderedDict
Normal dicts keep insertion order since Python 3.7. OrderedDict still adds move_to_end() and an order-sensitive ==, which is handy for simple caches:
from collections import OrderedDict cache = OrderedDict(a=1, b=2, c=3)cache.move_to_end("a")print(list(cache))cache.popitem(last=False) # remove the oldestprint(list(cache))['b', 'c', 'a'] ['c', 'a']
ChainMap
ChainMap looks up keys in several dicts in order, without copying them. It is a neat way to layer settings:
from collections import ChainMap defaults = {"browser": "chromium", "headless": True, "timeout": 30}env = {"headless": False}cli = {"timeout": 60} settings = ChainMap(cli, env, defaults)print(settings["browser"], settings["headless"], settings["timeout"])chromium False 60
Which one to use
| Need | Use |
|---|---|
| Count occurrences | Counter |
| Group items into lists or sets | defaultdict(list) / defaultdict(set) |
| Queue or stack with fast ends | deque |
| Lightweight record with names | namedtuple (or dataclass) |
| Layered configuration | ChainMap |
Check your understanding
Predict the output
from collections import Counter, defaultdictc = Counter("hello")d = defaultdict(int)d["x"] += 5print(c["l"], c["z"], dict(d))2 0 {'x': 5}“hello” has two ls and no z (a Counter returns 0 for missing keys). The defaultdict creates x with int() = 0, then adds 5.
Quick quiz
1. Which container counts items automatically?
Counter(iterable) maps each item to its count.
2. What does defaultdict(list) give for a missing key?
The factory list() creates the default value.
3. Which is fastest for removing items from the front?
A deque is designed for fast operations at both ends.
Exercise: most frequent words
Print the three most common words in the text, ignoring case and punctuation.
"Test early. Test often! Automate the test, then test again."
test 4 early 1 often 1
Hint 1
Lower-case the text, replace punctuation with spaces, then use Counter(words).most_common(3).
from collections import Counter text = "Test early. Test often! Automate the test, then test again."for mark in ".,!": text = text.replace(mark, " ")words = text.lower().split() for word, count in Counter(words).most_common(3): print(word, count)test 4 early 1 often 1
Removing punctuation first makes “test,” and “Test” count as the same word. most_common(3) returns (word, count) pairs, highest first; ties keep their first-seen order.
Program Practice
20 Python Collections Programs
Every program has a step-by-step explanation, colour-coded code and its real output.
Python collections FAQ
What is Counter in Python?
collections.Counter is a dict subclass that counts hashable items. Counter("banana") gives {'a': 3, 'n': 2, 'b': 1}.
What is the difference between dict and defaultdict?
A normal dict raises KeyError for a missing key. A defaultdict creates the key with a default value from the factory you supplied.
When should I use deque instead of list?
When you add or remove items at the front, as in a queue. A deque does this in constant time; a list has to shift every item.
1 thought on “Python Collections Module”