ML Foundations
Avoid inserting missing keys while inspecting a defaultdict
Understand why bracket access creates a group and how get can inspect an absent key without adding it.
Evidence and testing
Review record: Tensor Almanac automated evidence gate (no independent human review). Example versions, recorded outputs and limitations appear below.
A read can change the set of groups
A defaultdict is convenient when collecting training examples by split or label. With a list factory, bracket access to an absent key creates an empty list and stores it in the mapping. A inspection can therefore add a group that had not appeared in the input. [1]
This matters when later code enumerates groups or counts observed labels. An empty created group and a genuinely observed group are different states. Preserve that distinction deliberately instead of assuming every lookup is read-only.
References: [1]
Compare get and bracket lookup
Run python examples/defaultdict_read_inserts.py. The example first adds one item to the training group. Calling get on the absent test key returns None and leaves the keys unchanged. Bracket access to that same key then creates an empty list, and the next key listing includes test. [1, 2]
The output and assertions show the mapping after each step. Python documents that the defaultdict missing-key mechanism is used by bracket lookup, whereas get returns its default without invoking that mechanism. Supplying an explicit default to get can change the returned value but still does not add the missing key. [1, 2]
Use bracket access when creating a group is intended. For inspection, get or a membership test is often clearer. If None could itself be a stored value, use membership or a separate sentinel to distinguish absent from present.
Executed with Python 3.12.14; stdout and checksum are in private evidence.
"""Contrast missing-key lookup and get on a defaultdict of batch IDs."""
from collections import defaultdict
batches = defaultdict(list)
batches['train'].append(12)
print('initial keys:', sorted(batches))
print('get absent:', batches.get('test'))
print('after get:', sorted(batches))
print('bracket absent:', batches['test'])
print('after brackets:', sorted(batches))
assert sorted(batches) == ['test', 'train']
assert batches['test'] == []
Recorded output
initial keys: ['train'] get absent: None after get: ['train'] bracket absent: [] after brackets: ['test', 'train']
Keep the example in scope
This example uses a list factory and ordinary string keys. It does not exercise concurrent access, other custom factories, malformed data or a particular machine-learning framework. The output illustrates dictionary state, not a performance or model-quality comparison.
A factory can return an object with its own behavior, so inspect the actual factory when debugging a real application. Avoid treating an empty list returned by get as proof that the group was present unless the program also checks membership.