Python Tutorial › Modules › Collections

Python Collections Module

IntermediateLesson 37 of 4711 min read9 runnable examples

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.

Advertisement
In this lesson
  • 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.

Python
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))
Output
Counter({'the': 3, 'and': 2, 'cat': 1, 'hat': 1, 'bat': 1})
3 0
[('the', 3), ('and', 2)]

Counting characters, and doing arithmetic with counters:

Python
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])
Output
[('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:

Python
from collections import Counterprint(Counter("listen") == Counter("silent"), Counter("apple") == Counter("paple"))
Output
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…

Python
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))
Output
{'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.

Python
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)
Output
deque(['urgent', 'task1', 'task2', 'task3'])
urgent
task3
deque(['task1', 'task2'])

maxlen keeps only the last N items, perfect for “recent history”:

Python
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)
Output
['product', 'cart', 'checkout']
deque([4, 5, 1, 2, 3])

namedtuple: tuples with field names

Python
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))
Output
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:

Python
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))
Output
['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:

Python
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"])
Output
chromium False 60

Which one to use

NeedUse
Count occurrencesCounter
Group items into lists or setsdefaultdict(list) / defaultdict(set)
Queue or stack with fast endsdeque
Lightweight record with namesnamedtuple (or dataclass)
Layered configurationChainMap

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))

Quick quiz

1. Which container counts items automatically?

2. What does defaultdict(list) give for a missing key?

3. Which is fastest for removing items from the front?

Exercise: most frequent words

Print the three most common words in the text, ignoring case and punctuation.

Input
"Test early. Test often! Automate the test, then test again."
Expected output
test 4
early 1
often 1
Hint 1

Lower-case the text, replace punctuation with spaces, then use Counter(words).most_common(3).

Program Practice

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”

Leave a Comment