Lesson 12 — Key-Value Stores

Dictionaries

The Python dict is the most important data structure after the list. Fast O(1) key-based lookup, flexible values, and dict comprehensions make it indispensable.

PYTHON — Dict basics
# Creation:
learner = {
    "name":   "Thandi Mokoena",
    "age":    21,
    "course": "Python",
    "mark":   74.5,
    "active": True
}

# Access:
print(learner["name"])             # Thandi Mokoena
print(learner.get("city"))         # None — no error
print(learner.get("city", "Unknown"))  # Unknown — with default

# Add or update:
learner["city"] = "Johannesburg"
learner["mark"] = 82.0             # updates existing key

# Delete:
del learner["active"]
removed = learner.pop("age")       # removes and returns the value
print(removed)                     # 21
PYTHON — Iterating
# Iterating:
for key in learner:
    print(f"{key}: {learner[key]}")

# Preferred — iterate key-value pairs:
for key, value in learner.items():
    print(f"{key}: {value}")

# Just keys or just values:
print(list(learner.keys()))
print(list(learner.values()))

# Membership test — checks keys:
print("name" in learner)   # True
print("Thandi" in learner) # False — checks keys, not values

Dict Comprehensions

PYTHON — Dict comprehensions
marks = {"Thandi": 74.5, "Sipho": 81.0, "Lerato": 58.0, "Bongani": 88.5}

# Filter — only passing learners:
passing = {name: m for name, m in marks.items() if m >= 50}
print(passing)

# Transform values:
graded = {name: ("Pass" if m >= 50 else "Fail")
          for name, m in marks.items()}
print(graded)

# Create from two lists (zip):
names  = ["Thandi", "Sipho", "Lerato"]
scores = [74.5, 81.0, 58.0]
mark_dict = dict(zip(names, scores))
print(mark_dict)

Nested Dicts and defaultdict

PYTHON — Nested dicts
from collections import defaultdict

# Nested dict — learner profiles by course:
cohort = {
    "Java":   [{"name": "Thandi", "mark": 74.5}],
    "Python": [{"name": "Sipho",  "mark": 81.0}]
}
cohort["SQL"] = [{"name": "Lerato", "mark": 68.0}]
print(cohort["Java"][0]["name"])  # Thandi

# defaultdict — auto-creates missing keys:
by_course = defaultdict(list)  # default is an empty list
for name, course, mark in [
        ("Thandi","Java",74.5),("Sipho","Python",81.0),
        ("Lerato","Java",68.0),("Bongani","SQL",88.5)]:
    by_course[course].append({"name": name, "mark": mark})

for course, learners in by_course.items():
    avg = sum(l["mark"] for l in learners) / len(learners)
    print(f"{course}: {len(learners)} learners, avg {avg:.1f}%")

Practice Task

Your Turn

Build a word frequency counter: given a string of text, create a dict mapping each word to its count. Sort by frequency descending and print the top 10 words. Then create a dict of course: list_of_learners from a flat list of (name, course, mark) tuples. Compute and print the average mark per course.

Common Mistakes

  • d[key] raises KeyError — always use d.get(key) or check with key in d first.
  • Dict keys must be hashable — lists and dicts cannot be keys.
  • Iterating a dict and modifying it simultaneously — RuntimeError. Use a copy: dict(d).
  • defaultdict changes how missing keys behave — don't forget you're using one.

Professional Tip

Dictionaries are how Python represents structured data — JSON, configuration, database rows, function keyword arguments. Mastering dicts is essential for every Python domain.

Mini Quiz

What does dict.get('key') return if 'key' does not exist?