Dictionaries
A list finds items by position: scores[0], scores[1]. Often it's much more natural to find things by name: a word's definition, a user's email, a product's price. A dictionary stores key-value pairs, so you look up a value using its key.
Creating a dictionary
Write key: value pairs inside curly braces:
person = {
"name": "Ada",
"age": 36,
"city": "London",
}
print(person)
print(type(person))
print(len(person)) # number of pairsKeys are usually strings, but they can be numbers or tuples too. Each key appears only once in a dictionary. Values can be anything, including lists or other dictionaries.
Looking up values
Put the key in square brackets:
person = {"name": "Ada", "age": 36, "city": "London"}
print(person["name"])
print(person["age"])Asking for a key that doesn't exist raises a KeyError:
person = {"name": "Ada", "age": 36}
print(person["email"])Safer lookups with get()
get() returns None instead of crashing, or a default value that you choose:
person = {"name": "Ada", "age": 36}
print(person.get("name"))
print(person.get("email"))
print(person.get("email", "no email"))Use in to check whether a key exists:
person = {"name": "Ada", "age": 36}
print("age" in person)
print("email" in person)Adding and changing entries
Assigning to a key adds it if it's new, or replaces its value if it already exists:
stock = {"apples": 10, "pears": 4}
stock["bananas"] = 7 # add
stock["apples"] = 12 # update
stock["pears"] += 1 # update based on the old value
print(stock)update() adds or changes several entries at once:
stock = {"apples": 10}
stock.update({"pears": 3, "apples": 15})
print(stock)Going deeper: Merging dictionaries optional
update() changes a dictionary in place. To build a new merged dictionary instead, use the | operator. When both sides have the same key, the value on the right wins:
defaults = {"theme": "light", "font_size": 14}
choices = {"font_size": 18}
settings = defaults | choices
print(settings)
print(defaults) # unchangedYou may also see the older spelling {**defaults, **choices}, which does the same thing.
Removing entries
stock = {"apples": 10, "pears": 4, "bananas": 7, "kiwis": 2}
removed = stock.pop("pears") # remove and return the value
print(removed, stock)
del stock["bananas"] # remove
print(stock)
stock.clear() # remove everything
print(stock)Keys, values and items
Three methods give you views of the dictionary's contents:
prices = {"coffee": 3.5, "tea": 2.8, "juice": 4.0}
print(list(prices.keys()))
print(list(prices.values()))
print(list(prices.items())) # list of (key, value) tuplesThese come in handy for calculations:
prices = {"coffee": 3.5, "tea": 2.8, "juice": 4.0}
print(sum(prices.values()))
print(max(prices.values()))
print(sorted(prices)) # sorted keysYou'll loop over these in the For Loops lesson, which is where dictionaries really shine.
Counting with a dictionary
A very common pattern is counting things. get(key, 0) gives 0 the first time a key is seen:
votes = {}
votes["red"] = votes.get("red", 0) + 1
votes["blue"] = votes.get("blue", 0) + 1
votes["red"] = votes.get("red", 0) + 1
print(votes)Going deeper: Counting the easy way with Counter optional
Counting is so common that Python has a ready-made tool for it. Counter from the collections module counts everything in a list in one step:
from collections import Counter votes = ["red", "blue", "red", "green", "red", "blue"] counts = Counter(votes) print(counts) print(counts["red"]) print(counts["purple"]) # missing keys count as 0, no KeyError print(counts.most_common(2)) # the two most common, as (value, count) pairs
A Counter is a dictionary underneath, so everything from this lesson still works on it.
Going deeper: Dictionaries inside dictionaries optional
Values can be lists or other dictionaries, which lets you model structured data:
student = {
"name": "Mia",
"grades": [88, 92, 79],
"address": {
"city": "Leeds",
"postcode": "LS1 4AP",
},
}
print(student["grades"][1])
print(student["address"]["city"])
student["grades"].append(95)
print(student["grades"])This is exactly the shape of JSON, the format most web APIs use to send data.
Going deeper: What can be a key? optional
Keys must be immutable: strings, numbers and tuples work, but lists don't:
distances = {("London", "Paris"): 344}
print(distances[("London", "Paris")])
bad = {["a", "b"]: 1}Exercises
Exercise 1: Contact card
Create a dictionary for a contact with keys name, phone and email, then print the phone number.
contact = {}
Write key: value pairs inside the curly braces, separated by commas.
Read the phone number with contact["phone"].
Exercise 2: Update the inventory
Sell 3 apples, add a new item "mangos" with 6 in stock, and remove "pears". It should print {'apples': 7, 'bananas': 5, 'mangos': 6}.
inventory = {"apples": 10, "pears": 4, "bananas": 5}
print(inventory)inventory["apples"] -= 3 sells three apples.
Add a new key by assigning to it, and remove one with del inventory["pears"].
Exercise 3: Safe lookup
Look up the capital of country. If the country isn't in the dictionary, print Unknown instead of crashing.
capitals = {"France": "Paris", "Japan": "Tokyo", "Kenya": "Nairobi"}
country = "Brazil"
get() takes a second argument: the value to return when the key is missing.
Exercise 4: Order total
The order dictionary maps items to quantities, and prices maps items to prices. Calculate the total for coffee and cake and print Total: 12.0.
prices = {"coffee": 3.0, "cake": 4.5, "tea": 2.5}
order = {"coffee": 1, "cake": 2}
Multiply each item's price by its quantity, like prices["coffee"] * order["coffee"].
Add the coffee and cake amounts together, then print them after "Total:".
Dictionary methods at a glance
Each example starts from d = {"a": 1, "b": 2}. The Result column shows what the method gives back, or what d looks like afterwards for methods that change it.
| Method | What it does | Example | Result |
|---|---|---|---|
get(key, default) |
Value for key, or default (None if not given) when missing |
d.get("c", 0) |
0 |
keys() |
All the keys | list(d.keys()) |
['a', 'b'] |
values() |
All the values | list(d.values()) |
[1, 2] |
items() |
All the pairs, as (key, value) tuples |
list(d.items()) |
[('a', 1), ('b', 2)] |
update(other) |
Adds or replaces entries from another dictionary | d.update({"b": 5, "c": 3}) |
{'a': 1, 'b': 5, 'c': 3} |
pop(key, default) |
Removes key and returns its value (KeyError if missing and no default) |
d.pop("a") |
returns 1, leaves {'b': 2} |
popitem() |
Removes and returns the most recently added pair | d.popitem() |
returns ('b', 2), leaves {'a': 1} |
setdefault(key, value) |
Returns the value for key; if it's missing, adds it with value first |
d.setdefault("c", 0) |
returns 0, leaves {'a': 1, 'b': 2, 'c': 0} |
copy() |
Returns a new (shallow) copy | d.copy() |
{'a': 1, 'b': 2} |
clear() |
Removes every entry | d.clear() |
{} |
dict.fromkeys(keys, value) |
A new dictionary with every key set to value |
dict.fromkeys(["x", "y"], 0) |
{'x': 0, 'y': 0} |
Useful operations that aren't methods:
| Operation | What it does | Example | Result |
|---|---|---|---|
d[key] |
Value for key (KeyError if missing) |
d["b"] |
2 |
d[key] = value |
Adds or replaces an entry | d["c"] = 3 |
{'a': 1, 'b': 2, 'c': 3} |
del d[key] |
Removes an entry | del d["a"] |
{'b': 2} |
key in d |
Is key in the dictionary? |
"a" in d |
True |
len(d) |
Number of entries | len(d) |
2 |
d | other |
A new merged dictionary | d | {"c": 3} |
{'a': 1, 'b': 2, 'c': 3} |
Summary
- A dictionary maps keys to values:
{"name": "Ada"}. - Look up values with
d[key]. A missing key raisesKeyError. Used.get(key, default)to be safe. d[key] = valueadds or updates.pop()anddelremove.keys(),values()anditems()give you the contents.