Learn Python Dictionaries - get(), items(), pop(), Comprehensions (Tutorial #10)
Video: Learn Python Dictionaries - get(), items(), pop(), Comprehensions (Tutorial #10) by Taught by Celeste AI - AI Coding Coach
Python Dictionaries: get, items, pop, comprehensions
{key: value}. O(1) lookup, insert, delete. Iterating dicts (Python 3.7+) preserves insertion order. The most-used data structure in Python after lists and strings.
Dictionaries are Python's hash-map type — key-value pairs with fast lookup. Used for configurations, records, indexing, caches, and dispatch tables.
Creating a dict
ages = {"Alice": 30, "Bob": 25, "Charlie": 35}
empty = {}
print(ages) # {'Alice': 30, 'Bob': 25, 'Charlie': 35}
print(ages["Alice"]) # 30
Curly braces with key: value pairs. Empty: {} (or dict()).
Keys must be hashable (immutable) — strings, numbers, tuples (of hashables). Lists, dicts, sets are not hashable.
Access and modify
ages["Alice"] # 30
ages["Diana"] = 28 # add new key
ages["Alice"] = 31 # update existing
del ages["Bob"] # remove
d[key] reads or writes. del d[key] removes.
d["missing"] raises KeyError. To avoid:
ages.get("missing") # None (no error)
ages.get("missing", 0) # 0 (default)
"Alice" in ages # True (membership test)
.get(key, default) is the safe accessor.
Add, update, pop
ages = {"Alice": 30}
ages["Bob"] = 25 # add or update
ages.update({"Charlie": 35, "Alice": 31}) # merge in
print(ages)
# {'Alice': 31, 'Bob': 25, 'Charlie': 35}
removed = ages.pop("Bob") # remove and return value
print(removed) # 25
removed = ages.pop("missing", None) # default if missing
.update(other) merges another dict in. .pop(key) removes and returns; default avoids KeyError.
items, keys, values
for name in ages: # iterates keys
print(name)
for name in ages.keys(): # explicit keys
print(name)
for age in ages.values(): # values
print(age)
for name, age in ages.items(): # both — most useful
print(f"{name}: {age}")
.items() yields (key, value) pairs — the canonical way to iterate.
These are views — they reflect changes to the dict in real-time. To freeze, list(ages.keys()).
A contact book
contacts = {}
while True:
cmd = input("\nCommand (add/search/list/delete/quit): ")
if cmd == "add":
name = input("Name: ")
phone = input("Phone: ")
email = input("Email: ")
contacts[name] = {"phone": phone, "email": email}
print(f"Added {name}")
elif cmd == "search":
name = input("Search name: ")
if name in contacts:
info = contacts[name]
print(f" Phone: {info['phone']}")
print(f" Email: {info['email']}")
else:
print(f"{name} not found")
elif cmd == "list":
for name, info in contacts.items():
print(f" {name}: {info['phone']}, {info['email']}")
elif cmd == "delete":
if name in contacts:
del contacts[name]
else:
print(f"{name} not found")
elif cmd == "quit":
break
Nested dicts (contacts[name] is itself a dict). Common pattern for record-style data.
Dict comprehensions
squares = {x: x * x for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# Filter while building
big_squares = {x: x * x for x in range(10) if x > 5}
# Swap keys and values
ages = {"Alice": 30, "Bob": 25}
by_age = {age: name for name, age in ages.items()}
# {30: 'Alice', 25: 'Bob'}
{key_expr: value_expr for x in iterable}. Compact alternative to building a dict in a loop.
get with default
inventory = {"apples": 5, "bananas": 3}
count = inventory.get("apples", 0) # 5
count = inventory.get("oranges", 0) # 0 (default)
# Common pattern: count occurrences
counts = {}
for word in words:
counts[word] = counts.get(word, 0) + 1
The "get with default 0" idiom for counters. Or use Counter from collections:
from collections import Counter
counts = Counter(words)
setdefault
groups = {}
for student, group in roster:
groups.setdefault(group, []).append(student)
setdefault(key, default) is "get the value, or insert default if missing, return it." For grouping into lists, perfect.
Or use defaultdict:
from collections import defaultdict
groups = defaultdict(list)
for student, group in roster:
groups[group].append(student)
defaultdict(list) auto-creates a new list on first access. Cleaner than manual setdefault.
Order is preserved (Python 3.7+)
d = {}
d["b"] = 2
d["a"] = 1
d["c"] = 3
list(d.keys()) # ['b', 'a', 'c'] — insertion order
Python 3.7+ guarantees iteration in insertion order. Before 3.7, order was implementation-defined.
For "dict that always sorts itself," use sortedcontainers.SortedDict (third party).
Merging dicts
a = {"x": 1, "y": 2}
b = {"y": 3, "z": 4}
# Python 3.5+
merged = {**a, **b} # {'x': 1, 'y': 3, 'z': 4}
# Python 3.9+
merged = a | b # same effect
Right side wins on key conflicts.
Dict from pairs
pairs = [("a", 1), ("b", 2), ("c", 3)]
d = dict(pairs) # {'a': 1, 'b': 2, 'c': 3}
d = dict(zip(["a", "b"], [1, 2])) # zip + dict
dict() accepts an iterable of pairs.
When to use dict vs list
| Need | Use |
|---|---|
| Lookup by key | dict |
| Ordered sequence | list |
| Frequency counting | dict (or Counter) |
| Many membership checks | dict (O(1)) or set |
| Random access by index | list |
For "lookup by name" — dict is the answer almost every time.
Common stumbles
KeyError on missing key. Use .get() with default.
Mutable default argument. def f(x, d={}) — same dict reused across calls. Use def f(x, d=None): if d is None: d = {}.
Iterating while modifying. for k in d: del d[k] — RuntimeError. Build a list of keys first: for k in list(d): del d[k].
{} for empty set. It's an empty dict. Use set() for set.
Unhashable keys. d[[1, 2]] = "value" errors — lists aren't hashable. Use tuples.
Reversed keys/values. dict.values() iterates values, not items. For both, use .items().
What's next
Lesson 11: functions. def, parameters, return values, scope, default arguments, keyword arguments.
Recap
{key: value} for dict literal. Access with d[key] (KeyError if missing) or .get(key, default). Add/update via d[k] = v or .update(). Remove via del d[k] or .pop(k). Iterate with .items() for (k, v) pairs. Order preserved since Python 3.7. Comprehensions: {k: v for ... in ...}. For counters and grouping, collections.Counter and defaultdict. For merging, {**a, **b} or a | b (3.9+).
Next lesson: functions.