← Home

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"]

Resources