Collections Module0%

Collections Module

Beginner12 min readUpdated: Jul 11, 2026
Study Materials

The Collections Module in Python

Python's built-in general-purpose containers—dict, list, set, and tuple—are versatile, but certain high-performance algorithmic tasks demand specialized data structures. The collections module provides high-performance container alternatives that eliminate boilerplate and dramatically optimize time complexity.


1. The Core Containers in collections

Output
collections
├── Counter # Frequency tracker for hashable objects
├── defaultdict # Dictionary with automatic default value factory
├── deque # Double-ended queue with O(1) pops and appends at both ends
├── namedtuple # Factory for creating tuple subclasses with named fields
├── OrderedDict # Dictionary preserving order with reordering methods
└── ChainMap # View for searching multiple dictionaries as one

2. namedtuple: Readable, Lightweight Records

Tuples access values by numeric indices (p[0], p[1]), which hurts readability. namedtuple assigns field names to each position while maintaining tuple immutability and near-zero memory overhead compared to full class instances:

Python
from collections import namedtuple
 
# Define schema
Point = namedtuple("Point", ["x", "y", "label"])
 
# Instantiate
p1 = Point(12, 25, "NodeA")
 
# Access by field name OR numeric index
print(f"Label: {p1.label}, Coordinates: ({p1.x}, {p1.y})")
print(p1[0]) # 12 (Indexable like a tuple)
 
# Immutability preserved
# p1.x = 99 # AttributeError: can't set attribute

3. deque: Double-Ended Queue ($O(1)$ Performance)

In Python, a standard list is a contiguous dynamic array. Calling list.pop(0) or list.insert(0, val) has an expensive $O(n)$ time complexity because every subsequent element must be shifted in memory.

A deque (pronounced "deck") is implemented as a doubly linked list of blocks, guaranteeing $O(1)$ instantaneous operations from both the left and right ends:

Python
from collections import deque
 
queue = deque(["Task1", "Task2", "Task3"], maxlen=4)
 
# Fast O(1) operations on both ends
queue.append("Task4") # Append right
queue.appendleft("PriorityTask") # Prepend left (Evicts Task4 because maxlen=4!)
 
print(list(queue))
# Output: ['PriorityTask', 'Task1', 'Task2', 'Task3']
 
# Fast O(1) removals
first = queue.popleft() # 'PriorityTask'
last = queue.pop() # 'Task3'
print(f"Remaining: {list(queue)}")

4. Counter: High-Speed Frequency Counting

Counter is a dictionary subclass specifically designed for counting items and analyzing distributions:

Python
from collections import Counter
 
words = ["apple", "banana", "apple", "orange", "banana", "apple", "mango"]
counts = Counter(words)
 
print(counts)
# Output: Counter({'apple': 3, 'banana': 2, 'orange': 1, 'mango': 1})
 
# Direct lookup of non-existent key returns 0 instead of KeyError!
print(counts["grapes"]) # 0
 
# Retrieve top N most frequent elements
top_two = counts.most_common(2)
print("Top 2:", top_two) # [('apple', 3), ('banana', 2)]
 
# Arithmetic between counters
c1 = Counter(a=3, b=1)
c2 = Counter(a=1, b=2)
print("Combined:", c1 + c2) # Counter({'a': 4, 'b': 3})

5. defaultdict: Eliminating KeyError

A standard Python dictionary raises a KeyError when accessing a key that does not exist. A defaultdict automatically invokes a callable factory function (such as list, int, or set) to initialize missing keys on first access:

Python
from collections import defaultdict
 
# 1. Grouping items into lists
grouped_students = defaultdict(list)
 
records = [("CS", "Aarav"), ("EE", "Priya"), ("CS", "Rohan"), ("ME", "Vikram")]
 
for department, student in records:
# No need to write: if department not in grouped_students: grouped_students[department] = []
grouped_students[department].append(student)
 
print(dict(grouped_students))
# Output: {'CS': ['Aarav', 'Rohan'], 'EE': ['Priya'], 'ME': ['Vikram']}
 
# 2. Integer counter factory
word_counts = defaultdict(int)
for char in "mississippi":
word_counts[char] += 1 # Missing keys initialize to int() -> 0
print(dict(word_counts))

6. Data Structure Decision Matrix

Use CaseBest StructureWhy?
First-In-First-Out (FIFO) queuecollections.deque$O(1)$ popleft() vs $O(n)$ in list
Frequency tallying / histogramcollections.CounterBuilt-in arithmetic & .most_common()
Grouping items by keycollections.defaultdict(list)Eliminates manual existence checks
Lightweight immutable recordcollections.namedtupleClean dot-notation with tuple efficiency

Multiple Choice Questions

1. What is the time complexity of removing an item from the beginning of a collections.deque using popleft()?

A. $O(n)$ B. $O(n^2)$ C. $O(1)$ D. $O(\log n)$ Answer: C Explanation: deque provides $O(1)$ constant time complexity for insertions and deletions at both ends, whereas standard list pop(0) is $O(n)$.


2. What happens when you query a key that has not been added to a collections.Counter?

A. It raises a KeyError B. It returns 0 C. It returns None D. It adds the key with value -1 Answer: B Explanation: Counter returns 0 for missing keys instead of raising a KeyError.


3. Which factory function passed to defaultdict allows appending elements to missing keys without initialization?

A. defaultdict(dict) B. defaultdict(list) C. defaultdict(set) D. defaultdict(tuple) Answer: B Explanation: Passing list as the factory function creates a new empty list [] for any accessed key that does not exist yet.


4. What is a key advantage of namedtuple over a standard dictionary for fixed records?

A. namedtuple fields can be dynamically reassigned at runtime B. namedtuple is memory-compact and immutable, with dot notation attribute access C. namedtuple cannot be iterated over D. namedtuple runs only on multi-core CPUs Answer: B Explanation: namedtuple instances are immutable and have a memory footprint identical to standard tuples, while providing readable dot notation like point.x.


5. What happens when you append an element to a deque that has already reached its configured maxlen?

A. An OverflowError is raised B. The item on the opposite end is automatically discarded C. The deque resizes itself automatically to double its capacity D. The new element is rejected Answer: B Explanation: When a bounded deque with maxlen is full, appending an item to one end automatically evicts an item from the opposite end.


Next Lesson

OS and Sys Modules

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Related Lessons

Previous LessonNext Lesson
Datetime ModuleOS and Sys Modules

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext