057. Dictionaries
Map unique keys to values for O(1) lookup
057. Dictionaries
Aryan’s RAM monitor builds a pid → process_info dict for instant lookup. When a new snapshot arrives, he can check if a process changed in O(1):
# Build index: pid → record
proc_index = {}
for proc in snapshot:
proc_index[proc["pid"]] = proc
# Later: look up by PID without scanning the whole list
pid = 1234
if pid in proc_index:
info = proc_index[pid]
print(f"{info['name']}: {info['rss_mb']:.0f} MB")
else:
print(f"PID {pid} not found")
# Safe lookup with a default
rss = proc_index.get(pid, {}).get("rss_mb", 0.0)The critical lesson: proc_index[pid] raises KeyError if the PID is gone (the process terminated between scans). .get(pid, default) handles that gracefully — essential in a monitor that runs continuously.
Aryan also stores his thresholds as a config dict:
thresholds = {"warn_mb": 500, "crit_mb": 1000, "interval_sec": 5}
warn = thresholds.get("warn_mb", 200) # safe — uses 200 if key missing💡 Fun fact: Python dicts have been insertion-ordered since Python 3.7 (2018) — iterating a dict yields keys in the order they were inserted. Before 3.7 this was just an implementation detail of CPython 3.6, and before that dicts had unpredictable ordering. This change was important for config file parsing, JSON serialization, and any code that expects predictable dict iteration order.
⚠️ Watch out: dict[key] raises a KeyError if the key is missing — this is one of the most common runtime exceptions in Python. Beginners access dict keys directly everywhere, then get mysterious KeyError crashes in production when a config key is absent or a process terminates. Always use .get(key, default) when a key might not exist, especially when reading external data.
🤔 Think about it: .get(key, default) returns the default but does not add the key to the dict. dict.setdefault(key, default) returns the default and inserts it into the dict. When would you want setdefault instead of get — and how does collections.defaultdict take this concept even further?
Learning objectives
- Add, access, and remove dict entries
- Use .get() for safe access with a default
- Iterate over dict keys, values, and items
Key concepts
- dict
- key-value
- get()
- O(1) lookup
Try it
Concept detail
Dicts (dictionaries) map keys to values. Keys must be hashable (immutable types). Create: {}, {“a”: 1, “b”: 2}, dict(a=1, b=2).
Access patterns: d[key] — raises KeyError if missing d.get(key) — returns None if missing (no exception) d.get(key, default) — returns default if missing
Mutation: d[key] = value — add or overwrite del d[key] — remove (KeyError if missing) d.pop(key, default) — remove and return value (safe with default) d.update(other) — merge another dict in
Iteration: for k in d: — keys only for k, v in d.items(): — key-value pairs d.keys(), d.values() — views
Dict lookup is O(1) average. Since Python 3.7+, insertion order is preserved.
Solution
def add_contact(book, name, number):
book[name] = number
return book
def get_number(book, name):
return book.get(name, "Not found")
def remove_contact(book, name):
if name in book:
del book[name]
return book
def list_names(book):
return sorted(book.keys())Tests
def test_add_contact():
book = {}
add_contact(book, "Alice", "555-1234")
assert book["Alice"] == "555-1234"
def test_add_overwrites():
book = {"Alice": "555-0000"}
add_contact(book, "Alice", "555-1234")
assert book["Alice"] == "555-1234"
def test_get_existing():
book = {"Alice": "555-1234"}
assert get_number(book, "Alice") == "555-1234"
def test_get_missing():
assert get_number({}, "Bob") == "Not found"
def test_remove_existing():
book = {"Alice": "555-1234", "Bob": "555-5678"}
remove_contact(book, "Alice")
assert "Alice" not in book
assert "Bob" in book
def test_remove_missing():
book = {"Alice": "555-1234"}
remove_contact(book, "Bob") # should not raise
assert len(book) == 1
def test_list_names():
book = {"Charlie": "1", "Alice": "2", "Bob": "3"}
assert list_names(book) == ["Alice", "Bob", "Charlie"]