The Python Dictionary Trick That Makes Interviewers Smile
There is one dictionary pattern that separates developers who learned Python from developers who understand Python. It shows up in grouping problems, counting problems, and graph problems. Every experienced Python developer recognizes it. Interviewers notice when you use it naturally. Here is the pattern and five problems where it applies.
The Pattern: defaultdict
from collections import defaultdict
groups = defaultdict(list)
data = [("Alice", "Engineering"), ("Bob", "Marketing"), ("Carol", "Engineering"),
("Dave", "Marketing"), ("Eve", "Engineering")]
for name, dept in data:
groups[dept].append(name)
print(dict(groups))
Output: {'Engineering': ['Alice', 'Carol', 'Eve'], 'Marketing': ['Bob', 'Dave']}
Without defaultdict you would write:
groups = {}
for name, dept in data:
if dept not in groups:
groups[dept] = []
groups[dept].append(name)
The defaultdict(list) version eliminates the key existence check entirely. When you access a missing key it automatically creates an empty list. The logic becomes a single line.
Problem 1: Count Word Frequencies
from collections import defaultdict
text = "the cat sat on the mat the cat"
freq = defaultdict(int)
for word in text.split():
freq[word] += 1
print(dict(freq))
Output: {'the': 3, 'cat': 2, 'sat': 1, 'on': 1, 'mat': 1}
defaultdict(int) initializes missing keys to 0. Each increment works without any key check. This is the standard Python pattern for frequency counting.
Problem 2: Build an Adjacency List
from collections import defaultdict
edges = [(1, 2), (1, 3), (2, 4), (3, 4), (4, 5)]
graph = defaultdict(list)
for src, dst in edges:
graph[src].append(dst)
graph[dst].append(src)
print(dict(graph))
Output: {1: [2, 3], 2: [1, 4], 3: [1, 4], 4: [2, 3, 5], 5: [4]}
Graph problems in interviews almost always require building an adjacency list first. This is the cleanest way to do it in Python.
Problem 3: Nested Grouping
from collections import defaultdict
data = [("Engineering", "London", "Alice"), ("Engineering", "Berlin", "Bob"),
("Marketing", "London", "Carol"), ("Engineering", "London", "Dave")]
nested = defaultdict(lambda: defaultdict(list))
for dept, city, name in data:
nested[dept][city].append(name)
print(dict({k: dict(v) for k, v in nested.items()}))
Output: {'Engineering': {'London': ['Alice', 'Dave'], 'Berlin': ['Bob']}, 'Marketing': {'London': ['Carol']}}
defaultdict(lambda: defaultdict(list)) creates a nested defaultdict on demand. This handles two-level grouping without any key existence checks at either level.
The Interview Follow-Up
Interviewers who see you use defaultdict naturally will often ask: "what happens if you access a key that does not exist in a regular dict versus a defaultdict?"
- Regular dict: raises
KeyError. defaultdict: calls the factory function and returns the default value without raising.
The follow-up to the follow-up: "when would you prefer a regular dict over defaultdict?"
When you want missing key access to be an error, not silently create a value. For example, looking up a user ID that should exist in a database. If the ID is missing you want to know about it, not silently create an empty list.
Practice dictionary tracing problems at PyCodeIt. PyCodeIt 2.0 is officially here! I’ve rebuilt your ultimate Python interview sandbox from the ground up. Whether you are a computer science student, a data science graduate, or a developer preparing to ace technical interviews, Python code tracing is a highly tested yet rarely practiced skill. PyCodeIt is built specifically to bridge that gap, and our latest update changes everything.
Comments
No comments yet. Start the discussion.