Dictionary Methods Deep Dive
Reviewed & published by Brayan K
Dictionary methods are the built-in functions every dict carries — like get, setdefault, update, pop, and items — that let you read, change, and combine key-value data safely without ever risking a crash from a missing key.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You already know how to create a dictionary. Now you'll master the toolkit professionals reach for every single day to keep their code short, safe, and readable.
What You'll Learn in This Lesson
- Reading safely with get() and a default value
- Building up values with setdefault()
- Merging dictionaries with update() and |
- Removing keys with pop() and popitem()
- Looping over keys(), values(), and items()
- Transforming dicts with comprehensions
1 Reading Safely: get() and setdefault()
Accessing a missing key with square brackets raises a KeyError and stops your program. The get() method returns a fallback instead, and setdefault() goes one step further by inserting that fallback so you can build values up:
stock = {"apples": 12, "pears": 5}
# Square brackets CRASH on a missing key:
# print(stock["bananas"]) # KeyError!
# get() returns a safe default instead
print(stock.get("bananas")) # None
print(stock.get("bananas", 0)) # 0
print(stock.get("apples", 0)) # 12
# setdefault() READS and, if missing, WRITES
print(stock.setdefault("bananas", 0)) # 0 (and inserts it)
print(stock) # {'apples': 12, 'pears': 5, 'bananas': 0}# Group names by their first letter using setdefault()
names = ["Ada", "Ben", "Bea", "Cleo", "Amir"]
groups = {}
for name in names:
first = name[0]
# If 'first' is new, start an empty list, then append
groups.setdefault(first, []).append(name)
print(groups)
# ✅ Expected output:
# {'A': ['Ada', 'Amir'], 'B': ['Ben', 'Bea'], 'C': ['Cleo']}2 Merging: update(), | and |=
You often need to combine dictionaries — merging defaults with overrides, or folding new data into a record. The classic tool is update(); since Python 3.9 you also have the cleaner | (merge) and |= (in-place merge) operators:
defaults = {"theme": "light", "font": "sans", "size": 12}
user_prefs = {"theme": "dark", "size": 14}
# update() merges other INTO defaults, in place
settings = dict(defaults) # copy first so we don't wreck defaults
settings.update(user_prefs)
print(settings) # {'theme': 'dark', 'font': 'sans', 'size': 14}
# | builds a NEW dict (3.9+), originals untouched
merged = defaults | user_prefs
print(merged) # {'theme': 'dark', 'font': 'sans', 'size': 14}
print(defaults["theme"]) # light (unchanged!)
# |= merges in place, like update()
defaults |= {"size": 16}
print(defaults["size"]) # 16When keys collide, the right-hand dictionary always wins. That's exactly what you want for "defaults on the left, user choices on the right."
3 Removing, Viewing & Iterating
pop(key) removes a key and returns its value (with an optional default so it won't crash). popitem() removes and returns the last inserted pair. And keys(), values(), and items() give you live views for looping:
cart = {"book": 3, "pen": 1, "mug": 2}
# pop() removes a key and hands back its value
qty = cart.pop("pen")
print(qty, cart) # 1 {'book': 3, 'mug': 2}
# pop() with a default never raises KeyError
print(cart.pop("laptop", 0)) # 0
# popitem() removes the LAST inserted pair (LIFO)
last = cart.popitem()
print(last, cart) # ('mug', 2) {'book': 3}
# Loop over pairs with .items()
inventory = {"apple": 4, "pear": 7}
for name, count in inventory.items():
print(f"{name}: {count}")
# apple: 4
# pear: 7
# A dict comprehension transforms every value
doubled = {k: v * 2 for k, v in inventory.items()}
print(doubled) # {'apple': 8, 'pear': 14}# Safely remove cheap items while iterating
prices = {"coffee": 3, "tea": 2, "cake": 6, "water": 1}
# WRONG would be: for k in prices: ... del prices[k]
# RIGHT: iterate a snapshot of the keys
for name in list(prices.keys()):
if prices[name] < 3:
del prices[name]
print(prices)
# ✅ Expected output:
# {'coffee': 3, 'cake': 6}🎯 Your Turn: Fill in the Blanks
Replace each ___ so the tally counts every vote safely. Hint: get() with a default of 0 is perfect for counting.
# 🎯 YOUR TURN: count votes with get()
votes = ["red", "blue", "red", "green", "blue", "red"]
tally = {}
for color in votes:
# Add 1 to the running count, defaulting to 0 the first time
tally[color] = tally.___(color, ___) + 1
print(tally)
# Expected output:
# {'red': 3, 'blue': 2, 'green': 1}Common Errors
❌ Indexing a missing key
config = {"width": 80}
print(config["height"]) # KeyError: 'height'✅ Use get() with a default
print(config.get("height", 24)) # 24❌ Deleting while iterating the dict directly
for k in d:
del d[k] # RuntimeError: dictionary changed size during iterationfor k in list(d):
del d[k] # safe❌ Expecting update() to return the dict
merged = a.update(b) # merged is None!✅ Use the | operator for a new dict
merged = a | b # a real merged dictionary🎯 Mini Challenge: Merge & Summarize Orders
Combine two order batches into one, summing quantities for shared items, then report the busiest item.
# 🎯 Mini Challenge: merge two batches and find the top item
batch1 = {"apple": 4, "pear": 2, "plum": 1}
batch2 = {"pear": 5, "plum": 3, "kiwi": 6}
totals = dict(batch1)
for item, qty in batch2.items():
totals[item] = totals.get(item, 0) + qty
print("Totals:", totals)
# Find the item with the highest total
top_item = max(totals, key=totals.get)
print("Busiest:", top_item, "->", totals[top_item])
# Expected output:
# Totals: {'apple': 4, 'pear': 7, 'plum': 4, 'kiwi': 6}
# Busiest: pear -> 7📚 Keep Learning
- Python docs: Mapping Types — dict (every method explained)
- Python tutorial: Dictionaries
- Language reference: Dictionary displays & comprehensions
Frequently Asked Questions
Lesson complete — you handle dictionaries like a pro!
You can read safely with get(), build values with setdefault(), merge with update() and |, remove with pop() and popitem(), and loop cleanly over items() — all without a single KeyError or RuntimeError.
Practice quiz
Given stock = {'apples': 12}, what does stock.get('bananas') return?
- 0
- KeyError
- None
- ''
Answer: None. get() returns None for a missing key instead of raising KeyError.
What does stock.get('bananas', 0) return when 'bananas' is missing?
- 0
- None
- KeyError
- False
Answer: 0. get() returns the supplied default (0) when the key is absent.
What is the key difference between get() and setdefault()?
- They are identical
- get() inserts the key
- setdefault() only reads
- setdefault() inserts the key if missing; get() never changes the dict
Answer: setdefault() inserts the key if missing; get() never changes the dict. get() only reads; setdefault() reads AND inserts the default when the key is missing.
When merging with the | operator, if keys collide which value wins?
- The left-hand dict
- The right-hand dict
- It raises an error
- The smaller value
Answer: The right-hand dict. On key collisions, the right-hand dictionary's value wins.
What does a.update(b) return?
- None (it updates in place)
- The merged dict
- A copy of a
- b
Answer: None (it updates in place). update() mutates the dict in place and returns None.
Counting votes with tally[c] = tally.get(c, 0) + 1 over ['red','blue','red'] gives red = ?
- 1
- 3
- 2
- 0
Answer: 2. 'red' appears twice, so its count ends at 2.
Which raises 'RuntimeError: dictionary changed size during iteration'?
- Looping over list(d.keys()) and deleting
- Deleting keys while looping directly over the dict
- Using a dict comprehension
- Calling d.items()
Answer: Deleting keys while looping directly over the dict. Adding or removing keys while iterating the dict directly raises this RuntimeError.
What does cart.popitem() remove and return?
- The first inserted pair
- A random pair
- The largest value
- The last inserted pair
Answer: The last inserted pair. popitem() removes and returns the last inserted key-value pair (LIFO).
What is the safe way to delete keys while iterating?
- for k in d: del d[k]
- for k in list(d.keys()): ...
- del d
- d.clear() inside the loop
Answer: for k in list(d.keys()): .... Iterate over a snapshot like list(d.keys()) so the live dict can change safely.
Using setdefault, groups.setdefault(first, []).append(name) for ['Ada','Ben','Bea'] groups B as...
- ['Bea']
- ['Ben']
- ['Ben', 'Bea']
- ['Ada', 'Ben']
Answer: ['Ben', 'Bea']. Both Ben and Bea start with B, so the 'B' list becomes ['Ben', 'Bea'].
Continue this course
- Previous: Checkpoint: The Standard Library
- Next: Counter & defaultdict — Count and group data effortlessly with collections.Counter and defaultdict
- Quick reference: Python cheat sheet › Dicts & Sets
Frequently asked questions
Why use dict.get() instead of square brackets?
Square brackets raise a KeyError when the key is missing, which crashes your program. dict.get(key) returns None instead, and dict.get(key, default) returns a fallback value you choose. Use get() whenever a key might legitimately be absent — for example reading optional settings or counting things you've never seen before.
What's the difference between get() and setdefault()?
get() only reads — it returns a default but never changes the dictionary. setdefault(key, default) reads AND writes: if the key is missing it inserts it with the default and returns that, otherwise it returns the existing value. Reach for setdefault when you want to build up a value, such as appending to a list stored under a key.
Does the merge operator | modify my original dictionary?
No. The | operator (Python 3.9+) creates a brand-new dictionary, leaving both originals untouched. If you want to update a dictionary in place instead, use |= or the older d.update(other). When keys overlap, the value from the right-hand dictionary wins.
Why can't I add or remove keys while looping over a dictionary?
Changing a dictionary's size during iteration raises RuntimeError: dictionary changed size during iteration, because the loop relies on the structure staying stable. To delete while iterating, loop over a snapshot like list(d.keys()) or build a new dictionary with a comprehension and reassign it.