Dictionaries: Mapping Colors to Actions

Pre-COSMOS Day 12, for Cluster 10: Robot Inventors - an advanced session of 50 slides. Dictionaries are the natural way to map a color to an action, or a state to what comes next, which is exactly how the camp's finite-state robot logic works, and the diagnostic rated this fragile. The session covers key-to-value lookup, dictionaries against lists, and the KeyError trap, since keys are not numeric positions - it is actions["red"], not actions[0]. It then covers safe lookups with .get(key, default) and the in operator, adding and updating keys, len, and looping with keys(), values(), and items(), before two advanced patterns: the counter or tally, and the dictionary as a finite state machine. It builds to a fully scaffolded your-turn Cheat-Code Console - a codes dictionary, input, a .get default, and a while-quit loop - with a usage-tally stretch. There are five checks, three traps, two photos, and SVG diagrams of the lookup table and the FSM. Every snippet was run in real Python, covering the KeyErrors, .get, the tally, and the FSM transitions, with the output copied verbatim into the trace tables.

Subject: Python · 80 slides · code lesson

Open the interactive version of this deck · Homework for this lesson

What this lesson covers

The lesson, slide by slide

1. Dictionaries: Mapping Colors to Actions

Title

Day 12 · Cluster 10: Robot Inventors

The natural way to map a color to an action - or a state to what comes next. This is how the camp's finite-state robot logic works.

2. What you will be able to do

Objectives

A dict lets the robot answer "when I see X, do Y" instantly. The diagnostic rated this fragile - by the end you'll have it solid. You can:

3. What survived from Color & Seeing: Detecting a Color is a Mask?

Warm-up

Discussion prompt

Before we open Dictionaries: Mapping Colors to Actions: without looking back, what was the main idea of Color & Seeing: Detecting a Color is a Mask, 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:

Pre-COSMOS Lesson 5 of 8 (41 slides): how a computer 'sees' a color. A pixel is three numbers [R,G,B], each 0..255; a color image is a grid of pixels with shape (H, W, 3).

4. Why dictionaries matter for robots

Concept

A humanoid robot lit from above in the dark
See a color → look up the action. Instantly.

A robot constantly maps one thing to another: a color to an action, a state to the next state, a command to a response.

A dictionary is exactly that map - ask it by name and it hands back the answer, with no scanning through positions.

It was fragile on the diagnostic for one reason: people treated it like a list. Today we fix that for good.

5. Break it if you can: Why dictionaries matter for robots

Counterexample

Discussion prompt

A robot constantly maps one thing to another: a color to an action, a state to the next state, a command to a response.

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.

Answer:

A dictionary is exactly that map - ask it by name and it hands back the answer, with no scanning through positions.

6. Today's roadmap

Concept

Four ideas, then you build a console out of them:

Look up by key
actions["red"] - ask by name.
Safe lookups
.get(key, default) never crashes.
Loop & patterns
items(), a tally, a state machine.
Cheat-Code Console
Type a code, get a power-up.

7. Which is which: Today's roadmap

Matching

Match the pairs

From Today's roadmap — match each one to what it actually does. The descriptions have been shuffled.

  • c1. Look up by key
  • c2. Safe lookups
  • c3. Loop & patterns
  • c4. Cheat-Code Console
  • b1. actions["red"] - ask by name.
  • b2. .get(key, default) never crashes.
  • b3. items(), a tally, a state machine.
  • b4. Type a code, get a power-up.

Why: Look up by key, Safe lookups, Loop & patterns, Cheat-Code Console are easy to tell apart while they are sitting next to their descriptions and much harder afterwards, which is what this checks.

8. What a Dictionary Is

Section

Section 1

9. A dictionary maps keys to values

Concept

A dictionary stores key → value pairs in curly braces. You look something up by its key, and it hands back that key's value.

dictionary — A collection of key:value pairs, written {"red": "turn"}. Each key is unique and is how you find its value - there are no number positions.

10. By analogy: A dictionary maps keys to values

Analogy

Discussion prompt

Explain A dictionary maps keys to values by analogy to something with no Python 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:

A dictionary stores key → value pairs in curly braces. You look something up by its key, and it hands back that key's value.

11. Dictionary vs list

Concept

A list finds things by position; a dictionary finds them by name. That's the whole difference - and the source of every dict bug.

listdictionary
access byposition: 0, 1, 2key: "red"
examplecolors[0]actions["red"]
order is how you find ityesno - you ask by name
best fora sequencea mapping / lookup

12. Fill in: list for Dictionary vs list

Comparison

Comparison matrix

From Dictionary vs list: refill the list column from what you know. The rest of the table is as it appeared.

listdictionary
access byposition: 0, 1, 2key: "red"
examplecolors[0]actions["red"]
order is how you find ityesno - you ask by name
best fora sequencea mapping / lookup

13. Picture it first: A dict is a labeled lookup table

Picture it

Figure (svg): A two-row lookup table: red points to turn, green points to go

Ask by the label on the left.

Discussion prompt

Read the picture before the words. What is this showing, and what is the one thing it is built to make obvious? Commit to an answer, then read on.

Hint: Name the parts, then say what changes between them — and if nothing changes, say what is being held still.

Answer:

Picture a little table: each key on the left points to its value on the right. You don't count to it - you read across from the label.

14. A dict is a labeled lookup table

Intuition

Picture a little table: each key on the left points to its value on the right. You don't count to it - you read across from the label.

Figure (svg): A two-row lookup table: red points to turn, green points to go

Ask by the label on the left.

15. Teach it back: A dict is a labeled lookup table

Explain it

Discussion prompt

Explain A dict is a labeled lookup table 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:

Picture a little table: each key on the left points to its value on the right. You don't count to it - you read across from the label.

16. Looking up an action

Worked example

Build the map once, then ask it by key.

actions = {"red": "turn", "green": "go"}

print(actions["red"])
print(actions["green"])

actions["red"] reads across from the key "red" to its value.

lookupvalue
actions["red"]turn
actions["green"]go

17. What each one costs: Looking up an action

Trade off

Comparison matrix

From Looking up an action: every row here is a choice with a cost. Fill the value column, then say which row you would actually pick and what you give up for it.

lookupvalue
actions["red"]turn
actions["green"]go

18. Keys, not number positions

Concept

This is the big one. A dictionary has no positions. actions[0] does not mean "the first pair" - it looks for a key called 0, and there isn't one.

Always look up by the real key: actions["red"], never actions[0].

19. Something is wrong here: treating a dict like a list

Anomaly

Predict first

A student writes this, and it looks reasonable:

Reaching for the "first item" by position.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: There's no key 0 in the dict - dicts don't have number positions.

Look it up by its key.

Why: There's no key 0 in the dict - dicts don't have number positions.

20. Trap: treating a dict like a list

Trap

The trap

Reaching for the "first item" by position.

Write actions[0]

Why: There's no key 0 in the dict - dicts don't have number positions.

Python raises KeyError: 0

Why: [ ] on a dict means "find this key", and key 0 doesn't exist.

The fix

Look it up by its key.

Write actions["red"]

Why: "red" is a real key, so the dict hands back its value.

Result: "turn"

Why: Keys are names, not positions - ask by the name you stored.

21. Rebuild the recipe: How to look something up

Ranking

Put in order

These are the steps of How to look something up, scrambled. Put them back in order before the next slide shows you.

  1. Ask by the key (a name), never by a number position.
  2. If the key is sure to exist, use d[key].
  3. If it might be missing, use d.get(key, default) so it can't crash.
  4. Not sure it's there? Check first with key in d.

Why: This is the order the recipe itself gives. Recalling the sequence without the slide in front of you is the difference between recognising the method and being able to run it — most of what goes wrong in practice is a step done out of turn.

22. How to look something up

Pattern

Every dictionary lookup you write follows this:

  1. Ask by the key (a name), never by a number position.
  2. If the key is sure to exist, use d[key].
  3. If it might be missing, use d.get(key, default) so it can't crash.
  4. Not sure it's there? Check first with key in d.

23. Where does it stop working: How to look something up

Edge cases

Discussion prompt

How to look something up works on the cases you have just seen. Push it to the edge: what is the most degenerate input it still handles — empty, zero, one item, everything equal — and what is the first case where it stops being true? Name the case, not just "it breaks".

Hint: Try the smallest legal input, then the largest, then the one where two things collide. Methods are specified at their edges; the middle takes care of itself.

Answer:

Every dictionary lookup you write follows this:

24. Check: keys, not positions

Check

Recall actions = {"red": "turn", "green": "go"}.

Check your understanding

What does actions[0] do?

  • A. Raises KeyError (correct)
  • B. Returns 'turn'
  • C. Returns 'red'
  • D. Returns None

Answer: A

Why: Dictionaries look things up by key. There is no key 0 in this dict, so actions[0] raises KeyError: 0. Use actions["red"].

Why B tempts people
That's list thinking - position 0. Dicts have no positions; [0] looks for a key 0, which isn't here.
Why C tempts people
Indexing a dict returns a value for a key, never a key - and 0 isn't a key anyway.
Why D tempts people
A missing key with square brackets raises KeyError; it's .get that returns None instead.

25. Safe Lookups with .get

Section

Section 2

26. KeyError vs .get

Concept

actions["blue"] on a missing key crashes with KeyError. actions.get("blue") returns None instead, and actions.get("blue", "wait") returns a default you choose.

.get(key, default) — Looks up key; if it's missing, returns default (or None if you give no default) instead of raising KeyError.

27. .get with and without a default

Worked example

Same dict, three lookups - watch the missing key.

actions = {"red": "turn", "green": "go"}

print(actions.get("red"))
print(actions.get("blue"))
print(actions.get("blue", "wait"))

"blue" isn't a key, so the default kicks in - no crash.

lookupresult
actions.get("red")turn
actions.get("blue")None
actions.get("blue", "wait")wait

28. Check first with in

Concept

key in d is True when the dictionary has that key. Handy before a d[key] lookup, or to branch on whether something is known.

in — color in actions tests whether color is a KEY of the dict (not a value). Returns True or False.

29. Membership test

Worked example

in checks keys, returning a simple True/False.

actions = {"red": "turn", "green": "go"}

print("red" in actions)
print("blue" in actions)

"red" is a key (True); "blue" is not (False).

testresult
"red" in actionsTrue
"blue" in actionsFalse

30. Something is wrong here: using [ ] for a key that might be missing

Anomaly

Predict first

A student writes this, and it looks reasonable:

Looking up player input directly with square brackets.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: If the key isn't there, the whole program crashes with KeyError.

Use .get with a safe default for anything that might miss.

Why: If the key isn't there, the whole program crashes with KeyError.

31. Trap: using [ ] for a key that might be missing

Trap

The trap

Looking up player input directly with square brackets.

actions[player_color] when input is "blue"

Why: If the key isn't there, the whole program crashes with KeyError.

One bad input = a crash

Why: Anything a user types could be a key you never stored.

The fix

Use .get with a safe default for anything that might miss.

actions.get(player_color, "wait")

Why: A missing key returns "wait" instead of crashing.

Bad input = a graceful default

Why: Use [ ] only for keys you're certain exist.

32. Break it on purpose: using [ ] for a key that might be missing

Break the constraint

Discussion prompt

The rule this trap just fixed:

A missing key returns "wait" instead of crashing.

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:

If the key isn't there, the whole program crashes with KeyError.

33. Rule out three: Check: .get default

Elimination

Eliminate the wrong options

What does actions.get("blue", "wait") return?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. 'wait'
  • B. Raises KeyError
  • C. None
  • D. 'blue'

Survives elimination: A

Why: "blue" isn't a key, so .get returns the default you supplied: "wait".

34. Check: .get default

Check

Recall actions = {"red": "turn", "green": "go"}.

Check your understanding

What does actions.get("blue", "wait") return?

  • A. 'wait' (correct)
  • B. Raises KeyError
  • C. None
  • D. 'blue'

Answer: A

Why: "blue" isn't a key, so .get returns the default you supplied: "wait".

Why B tempts people
.get never raises KeyError for a missing key - avoiding that crash is exactly its job.
Why C tempts people
None is what .get returns only when you give NO default; here the default is "wait".
Why D tempts people
.get returns the default value for a miss, not the key you looked up.

35. Change & Measure

Section

Section 3

36. Add and update keys

Concept

d[key] = value does double duty: if the key is new, it's added; if it already exists, its value is overwritten.

Keys are unique - a dict can't hold "red" twice, so a second assignment replaces the first.

37. What rests on this: Add and update keys

Socratic

Discussion prompt

d[key] = value does double duty: if the key is new, it's added; if it already exists, its value is overwritten.

Suppose that were not true. What is the first thing in Dictionaries: Mapping Colors to Actions that would stop working?

Hint: Follow it one step downstream. The answer is whatever was quietly relying on it.

Answer:

Keys are unique - a dict can't hold "red" twice, so a second assignment replaces the first.

38. Add a key, update a key

Worked example

Add "yellow" (new key), then change "red" (existing key).

actions = {"red": "turn", "green": "go"}
actions["yellow"] = "slow"
actions["red"] = "stop"

print(actions)
print(len(actions))

"yellow" is added; "red" is overwritten, not duplicated.

after linedictlen
startred:turn, green:go2
actions["yellow"]="slow"...yellow:slow added3
actions["red"]="stop"red now "stop"3

39. len counts keys

Concept

len(d) is the number of keys (which equals the number of pairs). Overwriting a key doesn't change it - only adding a new key does.

40. Where does each piece belong: Dictionaries: Mapping Colors to Actions

Sorting

Sort into buckets

These are the pieces of Dictionaries: Mapping Colors to Actions, out of order. Put each one back under the part of the lesson it belongs to.

What a Dictionary Is
A dictionary maps keys to values; Dictionary vs list; A dict is a labeled lookup table
Safe Lookups with .get
KeyError vs .get; .get with and without a default; Check first with in
Change & Measure
Add and update keys; Add a key, update a key; len counts keys
s1
What a Dictionary Is is where Dictionaries: Mapping Colors to Actions puts A dictionary maps keys to values, Dictionary vs list, A dict is a labeled lookup table. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s2
Safe Lookups with .get is where Dictionaries: Mapping Colors to Actions puts KeyError vs .get, .get with and without a default, Check first with in. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s3
Change & Measure is where Dictionaries: Mapping Colors to Actions puts Add and update keys, Add a key, update a key, len counts keys. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.

41. Something is wrong here: thinking re-assigning adds a pair

Anomaly

Predict first

A student writes this, and it looks reasonable:

Expecting len to grow every time you assign.

It is wrong. Say what breaks — and say it before you turn the page.

Correct: It looks like adding, so it feels like the count should rise.

Assigning an existing key updates its value in place.

Why: It looks like adding, so it feels like the count should rise.

42. Trap: thinking re-assigning adds a pair

Trap

The trap

Expecting len to grow every time you assign.

actions["red"] = "stop" when "red" exists

Why: It looks like adding, so it feels like the count should rise.

Expect len 2 → 3

Why: But "red" was already a key, so nothing new was added.

The fix

Assigning an existing key updates its value in place.

actions["red"] = "stop"

Why: "red"'s value changes from "turn" to "stop".

len stays 2

Why: Only a brand-new key raises the count.

43. Which of these survive contact with Dictionaries: Mapping Colors to Actions?

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.

Holds up
A robot constantly maps one thing to another: a color to an action, a state to the next state, a command to a response.; Four ideas, then you build a console out of them:; A dictionary stores key → value pairs in curly braces. You look something up by its key, and it hands back that key's value.
Breaks
Reaching for the "first item" by position.; Looking up player input directly with square brackets.
sound
These are stated as this lesson states them — each one survives the edge cases Dictionaries: Mapping Colors to Actions puts it through.
flawed
Each of these is lifted from a trap in this deck: reasonable-sounding, and wrong in a way that only shows up once you rely on it.

44. Check: len after an update

Check

Start from {"red": "turn", "green": "go"}.

Check your understanding

d = {"red": "turn", "green": "go"}
d["red"] = "stop"
print(len(d))

  • A. 2 (correct)
  • B. 3
  • C. 1
  • D. Raises an error

Answer: A

Why: "red" already exists, so d["red"]="stop" overwrites its value - no new key. len stays 2.

Why B tempts people
Assigning to an existing key updates its value; it doesn't add a second "red". Keys are unique.
Why C tempts people
Nothing is removed - both "red" and "green" are still keys, so len is 2, not 1.
Why D tempts people
Reassigning a key's value is normal and valid Python, not an error.

45. Looping Over a Dictionary

Section

Section 4

46. Looping gives you the keys

Concept

A plain for k in d: walks the keys. From each key you can reach its value with d[k].

47. for k in actions

Worked example

Each pass gives a key; actions[k] gets its value.

actions = {"red": "turn", "green": "go"}

for k in actions:
    print(k, actions[k])

k is the key each pass - never a number.

passkprints
1redred turn
2greengreen go

48. items(): key and value together

Concept

d.items() hands you both at once. Unpack them into two loop variables: for k, v in d.items():.

.items() — Yields each (key, value) pair, so for k, v in d.items() gives you both without a second lookup.

49. Term to definition: Dictionaries: Mapping Colors to Actions

Matching

Match the pairs

Match each term to the definition this lesson gave it — not the one you would guess from the word.

  • t1. dictionary
  • t2. .get(key, default)
  • t3. in
  • t4. .items()
  • d1. A collection of key:value pairs, written {"red": "turn"}. Each key is unique and is how you find its value - there are no number positions.
  • d2. Looks up key; if it's missing, returns default (or None if you give no default) instead of raising KeyError.
  • d3. color in actions tests whether color is a KEY of the dict (not a value). Returns True or False.
  • d4. Yields each (key, value) pair, so for k, v in d.items() gives you both without a second lookup.

Why: These are the working definitions of dictionary, .get(key, default), in, .items() as Dictionaries: Mapping Colors to Actions uses them. Pairing them correctly is the test of whether you could state each one with the slide switched off.

50. for k, v in actions.items()

Worked example

No actions[k] needed - you already have the value.

actions = {"red": "turn", "green": "go"}

for k, v in actions.items():
    print(k, "->", v)

k, v unpack each pair together.

passkv
1redturn
2greengo

51. keys() and values()

Concept

d.keys() gives just the keys; d.values() gives just the values. Wrap in list(...) to see them as a list.

d = {"red": "turn", "green": "go"}
print(list(d.keys()))
print(list(d.values()))
callresult
list(d.keys())['red', 'green']
list(d.values())['turn', 'go']

52. Fill in: result for keys() and values()

Comparison

Comparison matrix

From keys() and values(): refill the result column from what you know. The rest of the table is as it appeared.

callresult
list(d.keys())['red', 'green']
list(d.values())['turn', 'go']

53. Which loop should I use?

Intuition

Reach for .items() by default when you'll use the value - it saves a lookup and reads clearly.

54. Answer it before you see the options: Check: looping with items()

Prediction

Predict first

d = {"red": "turn", "green": "go"} for k, v in d.items(): print(k, v)

Answer it in your own words, now, with nothing to choose from. The options are on the next slide — and picking the right one off a list is an easier skill than producing it.

Correct: red turn / green go

Why: .items() yields (key, value) pairs, so k, v = 'red','turn' then 'green','go'. Each line prints the key then its value.

55. Check: looping with items()

Check

Predict the two printed lines.

Check your understanding

d = {"red": "turn", "green": "go"}
for k, v in d.items():
print(k, v)

  • A. red turn / green go (correct)
  • B. red green / turn go
  • C. 0 turn / 1 go
  • D. turn / go

Answer: A

Why: .items() yields (key, value) pairs, so k, v = 'red','turn' then 'green','go'. Each line prints the key then its value.

Why B tempts people
items() pairs each key WITH its own value, not all keys first then all values.
Why C tempts people
Dict loops give keys (and values), never numeric positions like 0 and 1.
Why D tempts people
That drops k; print(k, v) shows both the key and the value on each line.

56. Two Pro Patterns

Section

Section 5

57. Pattern 1: counting with a dict

Concept

To tally how often things appear, use the dict as a scoreboard: counts[item] = counts.get(item, 0) + 1.

The .get(item, 0) gives 0 the first time an item shows up, so you never crash on a key that isn't there yet.

58. Tallying colors seen

Worked example

Start empty; each color bumps its own count.

counts = {}
for color in ["red", "red", "green", "blue"]:
    counts[color] = counts.get(color, 0) + 1

print(counts)

.get(color, 0) returns 0 on first sight, then the running total.

seescounts.get(color,0)+1counts now
red0 + 1{red: 1}
red1 + 1{red: 2}
green0 + 1{red: 2, green: 1}
blue0 + 1{red: 2, green: 1, blue: 1}

59. Pattern 2: a dict as a state machine

Concept

Map each state to the next state. The robot's whole behavior loop becomes one dictionary lookup per step - this is finite-state logic.

Figure (svg): Three states forward, scan, turn in a cycle with arrows forward to scan to turn back to forward

next_state[state] returns where to go.

60. Teach it back: Pattern 2: a dict as a state machine

Explain it

Discussion prompt

Explain Pattern 2: a dict as a state machine 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:

Map each state to the next state. The robot's whole behavior loop becomes one dictionary lookup per step - this is finite-state logic.

61. The state machine, looping

Worked example

A wheeled robot car with an ultrasonic sensor facing a cardboard maze wall
Each step: look up the next state.

One dict drives the whole cycle; the loop just follows it.

next_state = {"forward": "scan",
              "scan": "turn",
              "turn": "forward"}
state = "forward"
for _ in range(4):
    print(state, "->", next_state[state])
    state = next_state[state]

next_state[state] is the lookup; reassigning state advances it.

stepstatenext_state[state]
1forwardscan
2scanturn
3turnforward
4forwardscan

62. Watch it run: The state machine, looping

Pattern

Step through it

Step through The state machine, looping one row at a time. What is driving the change, and what would the row after the last one be?

  1. Step 1: step is 1
  2. Step 2: step is 2
  3. Step 3: step is 3
  4. Step 4: step is 4

63. What makes a good key

Concept

Keys are usually strings (a color, a code, a state) or numbers - something stable you'll ask for by name. Each key is unique; the value can be anything.

Rule of thumb: if you find yourself asking "what's the X for this Y?", Y is your key and X is your value.

64. By analogy: What makes a good key

Analogy

Discussion prompt

Explain What makes a good key by analogy to something with no Python 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:

Keys are usually strings (a color, a code, a state) or numbers - something stable you'll ask for by name. Each key is unique; the value can be anything.

65. Rule out three: Check: the counting pattern

Elimination

Eliminate the wrong options

counts = {} for c in ["red", "red", "green"]: counts[c] = counts.get(c, 0) + 1 print(counts)

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. {'red': 2, 'green': 1}
  • B. {'red': 1, 'green': 1}
  • C. {'red': 3, 'green': 1}
  • D. KeyError: 'red'

Survives elimination: A

Why: .get(c, 0) returns 0 the first time and the running count after, so the two reds make red 2 and green is 1.

66. Check: the counting pattern

Check

Trace the tally to the end.

Check your understanding

counts = {}
for c in ["red", "red", "green"]:
counts[c] = counts.get(c, 0) + 1
print(counts)

  • A. {'red': 2, 'green': 1} (correct)
  • B. {'red': 1, 'green': 1}
  • C. {'red': 3, 'green': 1}
  • D. KeyError: 'red'

Answer: A

Why: .get(c, 0) returns 0 the first time and the running count after, so the two reds make red 2 and green is 1.

Why B tempts people
Each pass adds 1 to the previous count via .get(c,0)+1, so the second 'red' makes it 2, not 1.
Why C tempts people
There are two 'red's in the list, not three - red ends at 2.
Why D tempts people
counts.get(c, 0) supplies 0 for a key that isn't there yet, so the first 'red' doesn't crash.

67. Build It: Cheat-Code Console

Section

Section 6 · Your turn

68. The build: codes in, power-ups out

Concept

A dict maps secret codes to power-ups. The program reads what the player types and answers with .get - friendly default for codes it doesn't know. Type every line, run as you go, read errors - don't erase them.

#piecetool
1the codes mapa dict {code: power-up}
2read + respondinput() then .get(typed, default)
3keep goinga while loop until "quit"

69. Step 1 — the codes dictionary

Worked example

Your turn: make a dict codes mapping at least two secret codes to power-ups. Predict codes["UUDD"].

Hint: codes = {"UUDD": "extra life", "HESOYAM": "full health"}.

codes = {"UUDD": "extra life",
         "HESOYAM": "full health"}

print(codes["UUDD"])
lookupvalue
codes["UUDD"]extra life
codes["HESOYAM"]full health

70. Step 2 — read a code, respond safely

Worked example

Your turn: read what the player types and answer with .get and a friendly default. Why .get and not [ ]?

Hint: typed = input("Enter code: ") then print(codes.get(typed, "unknown code")).

typed = input("Enter code: ")
print(codes.get(typed, "unknown code"))
player typesoutput
UUDDextra life
HESOYAMfull health
XYZunknown code

71. Watch it run: Step 2 — read a code, respond safely

Pattern

Step through it

Step through Step 2 — read a code, respond safely one row at a time. What is driving the change, and what would the row after the last one be?

  1. Step 1: player types is UUDD
  2. Step 2: player types is HESOYAM
  3. Step 3: player types is XYZ

72. Step 3 — keep asking until "quit"

Worked example

Your turn: wrap it in a while loop so the player can keep entering codes until they type quit.

Hint: while True: ... if typed == "quit": break before the lookup.

while True:
    typed = input("Enter code: ")
    if typed == "quit":
        print("bye")
        break
    print(codes.get(typed, "unknown code"))
player typesoutput
UUDDextra life
ZZZunknown code
quitbye (loop ends)

73. What each one costs: Step 3 — keep asking until "quit"

Trade off

Comparison matrix

From Step 3 — keep asking until "quit": every row here is a choice with a cost. Fill the output column, then say which row you would actually pick and what you give up for it.

player typesoutput
UUDDextra life
ZZZunknown code
quitbye (loop ends)

74. Put it together: the console

Worked example

The whole program - a map, a loop, and one safe lookup.

codes = {"UUDD": "extra life",
         "HESOYAM": "full health"}

while True:
    typed = input("Enter code: ")
    if typed == "quit":
        print("bye")
        break
    print(codes.get(typed, "unknown code"))

.get keeps a wrong code from ever crashing the console.

sessionconsole says
UUDDextra life
hellounknown code
HESOYAMfull health
quitbye

If yours answers known codes, shrugs off unknown ones, and quits cleanly - you built it.

75. Fill in: console says for Put it together: the console

Comparison

Comparison matrix

From Put it together: the console: refill the console says column from what you know. The rest of the table is as it appeared.

sessionconsole says
UUDDextra life
hellounknown code
HESOYAMfull health
quitbye

76. Stretch — count how often each code is used

Worked example

Stretch: add a second dict that tallies uses - the counting pattern from earlier, inside your loop.

Hint: uses[typed] = uses.get(typed, 0) + 1 before the .get response; print uses when they quit.

uses = {}
# inside the loop, before responding:
uses[typed] = uses.get(typed, 0) + 1
# after the loop:
print(uses)
typed this sessionuses at quit
UUDD, UUDD, ZZZ{'UUDD': 2, 'ZZZ': 1}

77. Show it off

Concept

Explain your console in dictionary terms:

If you can answer all four, dictionaries are no longer fragile - they're your go-to tool.

78. Break it if you can: Show it off

Counterexample

Discussion prompt

If you can answer all four, dictionaries are no longer fragile - they're your go-to tool.

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.

79. Connect it up: Dictionaries: Mapping Colors to Actions

Connect it up

Draw it

One page, no notation unless you need it: draw how these connect — What a Dictionary Is · Safe Lookups with .get · Change & Measure · Looping Over a Dictionary · Two Pro Patterns · Build It: Cheat-Code Console. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.

80. What you can do now

Recap

taskthe move
look up a valueactions["red"]
safe lookupactions.get(c, "wait")
is the key there?c in actions
add / updateactions[c] = action
key + value loopfor k, v in d.items()
count thingsd[x] = d.get(x, 0) + 1

That's the data structure behind the robot's whole decision table - mapping what it senses to what it does.

Sources

  1. Python 3 Tutorial - Dictionaries
  2. Python 3 - dict.get and the mapping type methods (keys/values/items)
  3. Finite-state machines via dictionary dispatch / transition tables - concept reference
  4. All snippets executed in Python 3; output (KeyError: 'blue' / KeyError: 0, .get defaults, tally {'red':2,'green':1,'blue':1}, FSM transitions, Cheat-Code Console) copied verbatim into trace tables. — Author verification run, 2026-06-19 (Pre-COSMOS Prep Plan, Day 12).

Want this taught 1-on-1? Alexander tutors Python — $55/session, free consultation.

Book on Wyzant · Text (657) 465-8108