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.
United States
NORTH AMERICA
Related News

Mattress Firm Coupons: Save up to $600
4h ago
π I Built a Dropshipping Automation Pipeline β Here's What I Learned (and What I'd Do Differently)
11h ago
How I Cut My LLM API Bill by 40x: A Freelancer's Migration Story
11h ago
Cursor AI Review 2026: The AI-Native Code Editor
8h ago

Another Model Rewrote My Memories. Here's How I Caught It.
8h ago