Session 8 of the Python Fundamentals series, covered in depth. A dictionary maps a key to a value, and the session covers creating one, looking up with d[key] and with the safer d.get(key, default), adding and updating entries, checking for a key with in, len(), and looping over the keys and over .items(). It then replaces a long if/elif chain with a single lookup, tallies counts, and uses numeric keys. The traps are a KeyError on a missing key, indexing a dictionary as though it were a list, and duplicate keys overwriting one another. Every snippet and error message was copied verbatim from CPython 3.12.
Subject: Python Fundamentals · 95 slides · code lesson
Open the interactive version of this deck · Homework for this lesson
Title
Python Fundamentals - Session 8
Look things up by name, not by position
Objectives
Lists hold items in order; dictionaries hold pairs you look up by key. By the end you can:
d[key], and safely with d.get(key, default).in..items().Warm-up
Discussion prompt
Before we open Session 8 - Dictionaries: without looking back, what was the main idea of Session 7 - for Loops & Lists, and what could you do by the end of it that you could not do before?
Hint: One sentence for the idea, one for the skill. If the second one is blank, that is the part to revisit.
Answer:
That session covers lists and zero-based indexing, len(), the for loop, range() in three forms, append(), membership testing, and computing over a list.
Section
Part 1
Concept
A dictionary stores key -> value pairs. You look a value up by its key, like finding a word's meaning in a real dictionary.
dictionary (dict) — A collection of key: value pairs in curly braces. Each key is unique and maps to one value: {"France": "Paris"}.
Counterexample
Discussion prompt
A dictionary stores key -> value pairs. You look a value up by its key, like finding a word's meaning in a real dictionary.
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Concept
Write pairs as key: value, separated by commas, inside { }.
{"France": "Paris", "Japan": "Tokyo"} maps each country to its capital.
Analogy
Discussion prompt
Explain Making one: curly braces by analogy to something with no Python Fundamentals in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
Write pairs as key: value, separated by commas, inside { }.
Explain it to yourself
Discussion prompt
In A capitals dictionary this move is made:
Read the output
Why is that legal? Name the rule or definition it rests on before you read on.
Hint: If you can only say "because that is what you do", the rule is the thing to go and find.
Answer:
Verified by execution: prints the pairs in braces.
Worked example
capital = {"France": "Paris", "Japan": "Tokyo"}
print(capital)Two pairs, one dictionary
Why: Each country (key) maps to its capital (value).
Read the output
Why: Verified by execution: prints the pairs in braces.
| key | value |
|---|---|
| France | Paris |
| Japan | Tokyo |
Comparison
Comparison matrix
From A capitals dictionary: refill the value column from what you know. The rest of the table is as it appeared.
| key | value |
|---|---|
| France | Paris |
| Japan | Tokyo |
Concept
capital["Japan"] returns the value for that key - "Tokyo". The key goes in square brackets, just like list indexing.
But the 'index' here is a name, not a position.
Explain it
Discussion prompt
Explain Look up by key to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.
Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.
Answer:
capital["Japan"] returns the value for that key - "Tokyo". The key goes in square brackets, just like list indexing.
Worked example
capital = {"France": "Paris", "Japan": "Tokyo"}
print(capital["Japan"])The key selects the value
Why: "Japan" maps to "Tokyo".
Read the output
Why: Verified by execution: Tokyo.
| expression | value |
|---|---|
| capital["Japan"] | Tokyo |
Blank canvas
Draw it
Draw what Reading a value just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.
Intuition
Picture a wall of drawers, each with a name label. A list numbers the drawers 0, 1, 2; a dict names them 'France', 'Japan'.
To get a value you read the label, not count positions. That is the whole difference - and the whole point.
Concept
Each key appears once. Assigning to a key that already exists replaces its value rather than adding a second copy.
Anomaly
Predict first
A student writes this, and it looks reasonable:
Writing the same key twice, expecting both.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: A key can hold only one value, so the second "a": 2 replaces the first.
Use different keys for different pairs.
Why: A key can hold only one value, so the second "a": 2 replaces the first. The 1 is simply lost.
Trap
Writing the same key twice, expecting both.
d = {"a": 1, "a": 2}
print(d)The later value wins
Why: A key can hold only one value, so the second "a": 2 replaces the first. The 1 is simply lost.
| you write | actual |
|---|---|
| {"a": 1, "a": 2} | {'a': 2} |
Use different keys for different pairs.
d = {"a": 1, "b": 2}
print(d)Two distinct keys, two values
Why: Now both survive. Real output: {'a': 1, 'b': 2}. If you truly need several values under one key, store a list as the value.
| keys | kept |
|---|---|
| a, b | both |
Section
Part 2
Concept
Asking for a key that is not there with d[key] crashes with a KeyError.
This is the dict version of an index-out-of-range: you asked for something that does not exist.
Anomaly
Predict first
A student writes this, and it looks reasonable:
Brazil is not a key
It is wrong. Say what breaks — and say it before you turn the page.
Correct: d[key] demands the key exist. It does not, so Python raises a KeyError and stops.
Use .get() with a fallback for keys that might be missing.
Why: d[key] demands the key exist. It does not, so Python raises a KeyError and stops.
Trap
No entry for Brazil.
capital = {"France": "Paris"}
print(capital["Brazil"])Brazil is not a key
Why: d[key] demands the key exist. It does not, so Python raises a KeyError and stops.
| you write | result |
|---|---|
| capital["Brazil"] | KeyError: 'Brazil' |
Use .get() with a fallback for keys that might be missing.
capital = {"France": "Paris"}
print(capital.get("Brazil", "unknown")).get returns the fallback instead of crashing
Why: capital.get("Brazil", "unknown") is "unknown" because the key is absent. Real output: unknown.
| call | value |
|---|---|
| get("Brazil", "unknown") | unknown |
Break the constraint
Discussion prompt
The rule this trap just fixed:
Use .get() with a fallback for keys that might be missing.
Now break it on purpose. Build a case that violates it and follow the consequences until something visibly fails. Where does the failure first show up — and would you have noticed it if you had not been looking?
Hint: The dangerous rules are the ones whose violation still produces an answer. If yours fails loudly, try to find one that fails quietly.
Answer:
d[key] demands the key exist. It does not, so Python raises a KeyError and stops.
Concept
d.get(key, default) returns the value if the key exists, or the default you supply if it does not - never a crash.
If you omit the default, a missing key gives back None instead of an error.
Worked example
capital = {"France": "Paris", "Japan": "Tokyo"}
print(capital.get("Japan", "unknown"))
print(capital.get("Brazil", "unknown"))Present key returns its value
Why: Japan is there, so get returns Tokyo.
Missing key returns the default
Why: Verified by execution: Tokyo, then unknown.
| key | in dict? | get result |
|---|---|---|
| Japan | yes | Tokyo |
| Brazil | no | unknown |
Trade off
Comparison matrix
From Present vs missing: every row here is a choice with a cost. Fill the get result column, then say which row you would actually pick and what you give up for it.
| key | in dict? | get result |
|---|---|---|
| Japan | yes | Tokyo |
| Brazil | no | unknown |
Concept
"France" in capital checks whether that key exists - True or False. It looks at keys, not values.
Worked example
capital = {"France": "Paris", "Japan": "Tokyo"}
print("France" in capital)
print("Spain" in capital)in scans the keys
Why: France is a key; Spain is not.
Read the output
Why: Verified by execution: True then False. Use this before a d[key] to avoid a KeyError.
| expression | value |
|---|---|
| "France" in capital | True |
| "Spain" in capital | False |
Section
Part 3
Concept
d[key] = value either adds a new pair (if the key is new) or updates the value (if the key already exists).
One syntax does both - Python decides based on whether the key is already present.
Fill the middle
Fill in the blanks
From Add a new country — one line has had its right-hand side removed. Put it back.
capital = "Madrid"
capital["Spain"] = ___
print(capital)
Why: capital["Spain"] is what everything below it consumes, so the wrong expression here fails later and somewhere else. Verified by execution: now includes 'Spain': 'Madrid'.
Worked example
capital = {"France": "Paris", "Japan": "Tokyo"}
capital["Spain"] = "Madrid"
print(capital)Spain is new, so a pair is added
Why: The dict grows to three pairs.
Read the output
Why: Verified by execution: now includes 'Spain': 'Madrid'.
| before | after |
|---|---|
| 2 pairs | 3 pairs (+ Spain: Madrid) |
Explain it to yourself
Discussion prompt
In Update an existing value this move is made:
Japan already exists, so its value is replaced
Why is that legal? Name the rule or definition it rests on before you read on.
Hint: If you can only say "because that is what you do", the rule is the thing to go and find.
Answer:
Same key, new value - no second Japan is created.
Worked example
capital = {"Japan": "Tokyo"}
capital["Japan"] = "Kyoto"
print(capital)Japan already exists, so its value is replaced
Why: Same key, new value - no second Japan is created.
Read the output
Why: Verified by execution: {'Japan': 'Kyoto'}.
| key | old | new |
|---|---|---|
| Japan | Tokyo | Kyoto |
Error analysis
Annotate
Walk the callouts on Update an existing value. Each one is a place this is easy to get subtly wrong.
Concept
len(d) is how many key -> value pairs the dictionary holds.
Worked example
capital = {"France": "Paris", "Japan": "Tokyo"}
print(len(capital))Count the pairs
Why: Two keys, so two pairs.
Read the output
Why: Verified by execution: 2.
| dict | len |
|---|---|
| 2 pairs | 2 |
Section
Part 4
Concept
Looping over a dictionary gives you its keys, one per pass. Use the key to look up its value inside.
Explain it to yourself
Discussion prompt
In Loop over the keys this move is made:
Look up the value with the key
Why is that legal? Name the rule or definition it rests on before you read on.
Hint: If you can only say "because that is what you do", the rule is the thing to go and find.
Answer:
Verified by execution: France -> Paris, Japan -> Tokyo.
Worked example
capital = {"France": "Paris", "Japan": "Tokyo"}
for country in capital:
print(country, "->", capital[country])country takes each key
Why: France, then Japan.
Look up the value with the key
Why: Verified by execution: France -> Paris, Japan -> Tokyo.
| country | capital[country] |
|---|---|
| France | Paris |
| Japan | Tokyo |
Concept
for k, v in d.items(): hands you the key and the value together each pass - no separate lookup needed.
Worked example
capital = {"France": "Paris", "Japan": "Tokyo"}
for country, city in capital.items():
print(country, "->", city)Two loop variables, one per part
Why: country gets the key, city gets the value, each pass.
Read the output
Why: Verified by execution: same result, cleaner than looking up inside.
| country | city |
|---|---|
| France | Paris |
| Japan | Tokyo |
Intuition
Everything you did with list positions, you now do with dict keys: look up with d[key], test with in, walk with a for.
The mental swap is simply: 'which number?' becomes 'which name?'.
Section
Part 5
Concept
When an if/elif chain just maps inputs to outputs, a dictionary does the same job in one lookup.
The pairs live in data, not in code - easier to read, and easy to extend by adding one more entry.
Fill the middle
Fill in the blanks
From Canned replies as a dict — one line has had its right-hand side removed. Put it back.
replies = "hi"
msg = ___
print(replies.get(msg, "I don't get it"))
Why: msg is what everything below it consumes, so the wrong expression here fails later and somewhere else. replies[msg] would be the whole if/elif chain collapsed into data.
Worked example
replies = {"hi": "Hey!", "bye": "See ya!"}
msg = "hi"
print(replies.get(msg, "I don't get it"))One lookup instead of many ifs
Why: replies[msg] would be the whole if/elif chain collapsed into data.
.get supplies the else branch
Why: Verified by execution: prints Hey! An unknown msg would give the fallback.
| msg | reply |
|---|---|
| hi | Hey! |
| xyz (missing) | I don't get it |
Concept
A dict is perfect for counting: the item is the key, its running count is the value.
tally[item] = tally.get(item, 0) + 1 reads as 'current count (or 0) plus one'.
Pattern
Predict first
The table runs: red | {red: 1} · blue | {red: 1, blue: 1} · red | {red: 2, blue: 1} · red | {red: 3, blue: 1}
In Counting votes, given the rows so far: what is the next one — the row where v is blue?
Correct: blue | {red: 3, blue: 2}
| v | tally after |
|---|---|
| red | {red: 1} |
| blue | {red: 1, blue: 1} |
| red | {red: 2, blue: 1} |
| red | {red: 3, blue: 1} |
| blue | {red: 3, blue: 2} |
Why: The relationship between the columns, not the individual numbers, is what generates the next row. So it starts at 0 + 1 = 1, then climbs on repeats.
Worked example
votes = ["red", "blue", "red", "red", "blue"]
tally = {}
for v in votes:
tally[v] = tally.get(v, 0) + 1
print(tally)First time a color appears, get returns 0
Why: So it starts at 0 + 1 = 1, then climbs on repeats.
Trace the tally
Why: Verified by execution: {'red': 3, 'blue': 2}.
| v | tally after |
|---|---|
| red | {red: 1} |
| blue | {red: 1, blue: 1} |
| red | {red: 2, blue: 1} |
| red | {red: 3, blue: 1} |
| blue | {red: 3, blue: 2} |
Comparison
Comparison matrix
From Counting votes: refill the tally after column from what you know. The rest of the table is as it appeared.
| v | tally after |
|---|---|
| red | {red: 1} |
| blue | {red: 1, blue: 1} |
| red | {red: 2, blue: 1} |
| red | {red: 3, blue: 1} |
| blue | {red: 3, blue: 2} |
Faded example
Fill in the blanks
Build a dict in a loop, with the scaffolding fading: two lines are gone now — fill both.
pairs = [("pen", 2), ("book", 9)]
prices = cost
for item, cost in pairs:
prices[item] = ___
print(prices)
Why: Reproducing these unaided, rather than reading them, is what tells you the method has transferred. prices[item] = cost inserts one entry per pass.
Worked example
pairs = [("pen", 2), ("book", 9)]
prices = {}
for item, cost in pairs:
prices[item] = cost
print(prices)Start empty, add each pair
Why: prices[item] = cost inserts one entry per pass.
Read the output
Why: Verified by execution: {'pen': 2, 'book': 9}.
| item | prices after |
|---|---|
| pen | {pen: 2} |
| book | {pen: 2, book: 9} |
Cost model
Annotate
In Build a dict in a loop, before reading the notes: mark where the time actually goes. Which line dominates?
Section
Part 6
Anomaly
Predict first
A student writes this, and it looks reasonable:
Using a position number on a dict.
It is wrong. Say what breaks — and say it before you turn the page.
Correct: A dict has no positions. Python looks for a key 0, does not find one, and raises a KeyError.
A dict has no positions. Python looks for a key 0, does not find one, and raises a KeyError.
Why: A dict has no positions. Python looks for a key 0, does not find one, and raises a KeyError.
Trap
Using a position number on a dict.
capital = {"France": "Paris"}
print(capital[0])0 is treated as a key, not a position
Why: A dict has no positions. Python looks for a key 0, does not find one, and raises a KeyError.
| you write | result |
|---|---|
| capital[0] | KeyError: 0 |
Use an actual key.
capital = {"France": "Paris"}
print(capital["France"])Look up by name
Why: The key is "France", not a number. Real output: Paris. Dicts are indexed by key, lists by position.
| you write | value |
|---|---|
| capital["France"] | Paris |
Two truths and a lie
Sort into buckets
Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.
key: value, separated by commas, inside { }.; capital["Japan"] returns the value for that key - "Tokyo". The key goes in square brackets, just like list indexing.Concept
Keys are not limited to strings - numbers work as keys as well: {1: "A", 2: "B"}.
Even so, d[1] looks up the key 1, not the item at position 1. There is still no such thing as a position in a dict.
Worked example
grades = {1: "A", 2: "B"}
print(grades[1])1 is a key here
Why: grades[1] returns the value stored under the key 1.
Read the output
Why: Verified by execution: A.
| key | value |
|---|---|
| 1 | A |
| 2 | B |
Concept
Use a list when order and position matter, or items are all the same role (a queue of scores).
Use a dict when you look things up by a name or id (a country's capital, a user's score).
Section
Part 7
Concept
d.values() gives just the values. You can total them with sum(d.values()) or loop over them directly.
Worked example
scores = {"Ana": 84, "Ben": 55, "Cy": 110}
print(sum(scores.values()))sum adds every value
Why: 84 + 55 + 110.
Read the output
Why: Verified by execution: 249.
| values | sum |
|---|---|
| 84, 55, 110 | 249 |
Blank canvas
Draw it
Draw what Total the values just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.
Concept
To find which key has the largest value, loop over .items() and track the best so far - the same 'running maximum' idea as with lists.
Explain it
Discussion prompt
Explain Finding the biggest value to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.
Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.
Answer:
To find which key has the largest value, loop over .items() and track the best so far - the same 'running maximum' idea as with lists.
Pattern
Predict first
The table runs: Ana, 84 | Ana 84 · Ben, 55 | Ana 84
In Who scored highest?, given the rows so far: what is the next one — the row where name, s is Cy, 110?
Correct: Cy, 110 | Cy 110
| name, s | best so far |
|---|---|
| Ana, 84 | Ana 84 |
| Ben, 55 | Ana 84 |
| Cy, 110 | Cy 110 |
Why: The relationship between the columns, not the individual numbers, is what generates the next row. Each time a higher score appears, update both.
Worked example
scores = {"Ana": 84, "Ben": 55, "Cy": 110}
best = ""
best_score = -1
for name, s in scores.items():
if s > best_score:
best_score = s
best = name
print(best, best_score)Track the best name and score seen so far
Why: Each time a higher score appears, update both.
Trace the running best
Why: Verified by execution: Cy 110.
| name, s | best so far |
|---|---|
| Ana, 84 | Ana 84 |
| Ben, 55 | Ana 84 |
| Cy, 110 | Cy 110 |
Pattern
Step through it
Step through Who scored highest? one row at a time. What is driving the change, and what would the row after the last one be?
Concept
Values are not limited to single items - a value can be a whole list, which is how you group things under a key.
{"A": ["Ana", "Al"], "B": ["Ben"]} maps each group to its members.
Analogy
Discussion prompt
Explain A value can be a list by analogy to something with no Python Fundamentals in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.
Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.
Answer:
Values are not limited to single items - a value can be a whole list, which is how you group things under a key.
Worked example
roster = {"A": ["Ana", "Al"], "B": ["Ben"]}
print(roster["A"])
print(len(roster["A"]))The value is a list you can use normally
Why: roster["A"] is a list, so len() and indexing work on it.
Read the output
Why: Verified by execution: ['Ana', 'Al'] then 2.
| key | value (a list) | len |
|---|---|---|
| A | ['Ana', 'Al'] | 2 |
| B | ['Ben'] | 1 |
Error analysis
Annotate
Walk the callouts on Grouping with lists as values. Each one is a place this is easy to get subtly wrong.
Intuition
Two rules capture dicts: every key is unique, and each value can be anything - a number, a string, even a list or another dict.
That freedom is why dictionaries model so much real-world data: a profile, an inventory, a scoreboard.
Counterexample
Discussion prompt
Two rules capture dicts: every key is unique, and each value can be anything - a number, a string, even a list or another dict.
That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.
Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.
Fill the middle
Fill in the blanks
From A menu by lookup — one line has had its right-hand side removed. Put it back.
menu = input("Pick 1-3: ")
choice = ___
print(menu.get(choice, "invalid"))
Why: choice is what everything below it consumes, so the wrong expression here fails later and somewhere else. menu.get looks the option up, with a fallback for bad input.
Worked example
The user types 2, then 9:
menu = {"1": "Play", "2": "Score", "3": "Quit"}
choice = input("Pick 1-3: ")
print(menu.get(choice, "invalid"))The choice is the key
Why: menu.get looks the option up, with a fallback for bad input.
Read the output
Why: Verified by execution: 2 gives Score; 9 gives invalid.
| choice | result |
|---|---|
| 2 | Score |
| 9 | invalid |
Trade off
Comparison matrix
From A menu by lookup: every row here is a choice with a cost. Fill the result column, then say which row you would actually pick and what you give up for it.
| choice | result |
|---|---|
| 2 | Score |
| 9 | invalid |
Section
Part 8
Pattern
1. Look up with d[key], or d.get(key, default) if it might be missing
Why: d[key] crashes on a missing key; get returns your fallback instead.
2. Add or update with d[key] = value
Why: Same syntax adds a new pair or replaces an existing one.
3. Check keys with in; walk with for k, v in d.items()
Why: in tests keys; items() gives key and value together.
4. To count, use d[item] = d.get(item, 0) + 1
Why: The tally pattern - key is the thing, value is its running count.
Explain it to yourself
Discussion prompt
In Dict vs list, at a glance this move is made:
Both: use in to test membership, len() for size
Why is that legal? Name the rule or definition it rests on before you read on.
Hint: If you can only say "because that is what you do", the rule is the thing to go and find.
Answer:
For a list, in checks values; for a dict, in checks keys.
Pattern
Ordered items, same role -> list
Why: scores = [55, 84], accessed by position.
Look up by name/id -> dict
Why: capital = {"France": "Paris"}, accessed by key.
Both: use in to test membership, len() for size
Why: For a list, in checks values; for a dict, in checks keys.
Real world
Discussion prompt
Outside this lesson: where does Session 8 - Dictionaries actually turn up? Name one concrete situation — a job, a piece of software someone ships, a decision somebody has to make — and say which part of Dict vs list, at a glance is doing the work in it.
Hint: Vague is the failure mode here. "Engineering" is not a situation; "deciding whether this build is fast enough to ship" is.
Answer:
Session 8 of the Python Fundamentals series, in depth. Dictionaries map a key to a value: creating them, looking up with d[key] and the safe d.get(key, default), adding and updating, checking keys with in, len(), looping over keys and over .items(), replacing a long if/elif chain with one lookup, tallying counts, and numeric keys.
Check
Read the value for the key.
ages = {"Sam": 12, "Ana": 15}
print(ages["Ana"])| key | value |
|---|---|
| Ana | ? |
Check your understanding
What does this print?
Answer: A
Why: ages["Ana"] returns the value stored under the key Ana, which is 15. Verified by execution.
Check
The key is not present.
ages = {"Sam": 12}
print(ages["Ana"])| key present? | d[key] |
|---|---|
| no | ? |
Check your understanding
What happens?
Answer: A
Why: d[key] requires the key to exist. Ana is not in the dict, so Python raises a KeyError. ages.get("Ana", 0) would return 0 instead. Verified by execution.
Check
Key missing, but a default is given.
ages = {"Sam": 12}
print(ages.get("Ana", 0))| key present? | result |
|---|---|
| no | ? |
Check your understanding
What does this print?
Answer: A
Why: .get returns the default (0) when the key is missing, instead of crashing. Verified by execution.
Check
Does in look at keys or values?
capital = {"France": "Paris"}
print("Paris" in capital)| is Paris a key? | value |
|---|---|
| no (it is a value) | ? |
Check your understanding
What does this print?
Answer: A
Why: in checks the keys, and Paris is a value, not a key. The only key is France, so the result is False. Verified by execution.
Check
Same key assigned twice.
d = {"x": 1}
d["x"] = 5
print(d)| key | final value |
|---|---|
| x | ? |
Check your understanding
What does this print?
Answer: A
Why: Assigning to an existing key replaces its value, so x becomes 5. A key cannot appear twice. Verified by execution.
Check
Trace the counts.
t = {}
for x in ["a", "b", "a"]:
t[x] = t.get(x, 0) + 1
print(t)| x | t |
|---|---|
| a | ? |
| a | ? |
Check your understanding
What does this print?
Answer: A
Why: a appears twice and b once, so the tally is a: 2, b: 1. get(x, 0) starts each new key at 0. Verified by execution.
Comparison
Comparison matrix
From Check: the tally: refill the t column from what you know. The rest of the table is as it appeared.
| x | t |
|---|---|
| a | ? |
| a | ? |
Connect it up
Draw it
One page, no notation unless you need it: draw how these connect — Key maps to Value · Looking Up Safely · Adding & Updating · Looping Over a Dict · The Payoff · Pitfalls & Keys. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.
Recap
A dictionary maps keys to values. Look up by key, add/update by assignment, and loop over keys or .items().
| You want | Use |
|---|---|
| a value by key | d[key] |
| safe lookup | d.get(key, default) |
| add / update | d[key] = value |
| is the key there? | key in d |
| each pair | for k, v in d.items() |
| count things | d[x] = d.get(x, 0) + 1 |
Dicts are indexed by name, not position, and d[missing] is a KeyError - use .get when unsure. Next session we package code into reusable functions.
Want this taught 1-on-1? Alexander tutors Python Fundamentals — $55/session, free consultation.