Kodewick
Lesson 11 of 31Contents

Dictionaries

Lesson 11 of 31 · Part 2 · Collections and loops · about 15 minutes

A list finds things by position: item 0, item 1. A dictionary finds things by name. It stores pairs: a key, and the value that goes with it. Write them between curly braces as key: value, separated by commas.

main.py
1stock = {"coal": 40, "iron": 12, "gold": 3}2print(stock)3print(stock["iron"])4print(len(stock))5print(type(stock))
Output
{'coal': 40, 'iron': 12, 'gold': 3}
12
3
<class 'dict'>

Think of a warehouse ledger: look up "iron", read 12. len counts the pairs. Keys are usually strings, but numbers work too; values can be anything, including lists.

Looking up a value

dict[key] gives the value for that key. Keys are exact: "Iron" and "iron" are different keys. Ask for a key that is not there and Python stops with a KeyError, naming the missing key.

main.py
1stock = {"coal": 40, "iron": 12, "gold": 3}2print(stock["gold"])3print(stock["silver"])
Output
3
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    print(stock["silver"])
KeyError: 'silver'

in checks whether a key is in the dictionary. It does not look at the values.

main.py
1stock = {"coal": 40, "iron": 12, "gold": 3}2print("coal" in stock)3print(40 in stock)4if "silver" in stock:5    print(stock["silver"])6else:7    print("No silver yet")
Output
True
False
No silver yet

get(): a safe lookup

get(key) is like dict[key], but a missing key gives None instead of an error. Give it a second value and you get that instead of None.

main.py
1stock = {"coal": 40, "iron": 12}2print(stock.get("coal"))3print(stock.get("silver"))4print(stock.get("silver", 0))
Output
40
None
0

Use dict[key] when the key must be there, so a mistake shows up as an error. Use get when a missing key is normal.

Adding and changing

dict[key] = value does two jobs. If the key is new, it adds a pair. If the key is already there, it replaces the value. A key can appear only once.

main.py
1stock = {"coal": 40}2stock["iron"] = 123print(stock)4stock["coal"] = 355print(stock)6stock["coal"] = stock["coal"] + 57print(stock)8stock.update({"gold": 3, "iron": 20})9print(stock)
Output
{'coal': 40, 'iron': 12}
{'coal': 35, 'iron': 12}
{'coal': 40, 'iron': 12}
{'coal': 40, 'iron': 20, 'gold': 3}

update adds or replaces several pairs at once, from another dictionary. Dictionaries remember the order you added the keys in; changing a value does not move it.

Removing

del dict[key] deletes a pair. pop(key) deletes it and gives you the value. Both are a KeyError if the key is missing, unless you give pop a second value to use instead.

main.py
1stock = {"coal": 40, "iron": 12, "gold": 3}2del stock["coal"]3print(stock)4gold = stock.pop("gold")5print(gold, stock)6print(stock.pop("silver", 0))
Output
{'iron': 12, 'gold': 3}
3 {'iron': 12}
0

clear() empties the whole dictionary.

keys, values, items

keys() gives all the keys, values() all the values, and items() all the pairs as (key, value) tuples. Wrap them in list() to see them as plain lists. sum, max, sorted and in work on them too.

main.py
1stock = {"coal": 40, "iron": 12, "gold": 3}2print(list(stock.keys()))3print(list(stock.values()))4print(list(stock.items()))5print("Total ore:", sum(stock.values()))6print(sorted(stock))
Output
['coal', 'iron', 'gold']
[40, 12, 3]
[('coal', 40), ('iron', 12), ('gold', 3)]
Total ore: 55
['coal', 'gold', 'iron']

sorted(stock) sorts the keys: when you use a dictionary directly, as with in or sorted, you get its keys. In lesson 13, a for loop will walk through these one pair at a time.

Guess first

What does this print?

1d = {"a": 1, "b": 2}2d["a"] = 33d["c"] = 14print(len(d), sum(d.values()))

Counting with a dictionary

A dictionary is a natural tally: the thing is the key, its count is the value. The trick is get(key, 0) + 1: the first time, get gives 0, so the count starts at 1.

main.py
1found = "iron coal iron gold iron".split()2counts = {}3counts[found[0]] = counts.get(found[0], 0) + 14counts[found[1]] = counts.get(found[1], 0) + 15counts[found[2]] = counts.get(found[2], 0) + 16print(counts)
Output
{'iron': 2, 'coal': 1}

Press Step and watch counts grow: iron appears, then coal, then iron goes up to 2. Writing one line per word gets long; in lesson 13 a for loop does this for any number of words in two lines.

Tip: counts.get(word, 0) + 1 works whether or not the word has been seen before. counts[word] + 1 fails with a KeyError the first time.

What can be a key

A key must be a value that cannot change: a string, a number, a boolean, or a tuple of these. A list can change, so it cannot be a key. Python calls such values unhashable.

main.py
1lamps = {(4, 7): "lit", (2, 3): "dark"}2print(lamps[(4, 7)])3bad = {["coal"]: 1}
Output
lit
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    bad = {["coal"]: 1}
TypeError: unhashable type: 'list'

Values have no such rule. A value can be a list, or even another dictionary.

Methods at a glance

WriteWhat it does
d[k]the value for k (KeyError if missing)
d.get(k) / d.get(k, x)the value, or None / x if missing
d[k] = vadds the pair, or replaces the value
d.update(other)adds or replaces every pair of other
del d[k]deletes the pair
d.pop(k) / d.pop(k, x)deletes and gives back the value / x if missing
d.clear()deletes everything
k in dis k a key?
d.keys(), d.values(), d.items()the keys, the values, the (key, value) pairs
len(d)how many pairs

Practice

Write the code, then press Check. A hint costs nothing; the answer is there when you need it.

Exercise 1

A delivery

A cart brings 8 more iron and the first 5 silver. Update stock so it prints as shown.

It should print
{'coal': 40, 'iron': 20, 'silver': 5}
exercise1.py
1stock = {"coal": 40, "iron": 12}2# Your code here3print(stock)
Output
Press Run or Ctrl+Enter
Exercise 2

Ask nicely

Print the number of lamps on each street. Hill Street is not in the dictionary, so it should show 0, without an error.

It should print
2
0
exercise2.py
1lamps = {"Mill Lane": 4, "Pond Road": 2}2print(lamps["Pond Road"])3print(lamps["Hill Street"])
Output
Press Run or Ctrl+Enter
Exercise 3

Tally the ore

Count the three finds into counts with get, then print it.

It should print
{'gold': 2, 'coal': 1}
exercise3.py
1finds = ["gold", "coal", "gold"]2counts = {}3# Your code here4print(counts)
Output
Press Run or Ctrl+Enter

What you learned

  • A dictionary stores key: value pairs: {"coal": 40}. d[key] looks up a value.
  • A missing key is a KeyError; get(key, default) avoids it. in checks the keys.
  • d[key] = value adds or replaces; del, pop and clear remove.
  • keys(), values() and items() give the keys, the values and the pairs.
  • d[k] = d.get(k, 0) + 1 counts things.
  • Keys must be values that cannot change, such as strings, numbers and tuples, never lists.