TL;DR:
A list keeps items in order and allows duplicates. A dictionary maps keys to values. A set holds unique items with no order.
Use a dictionary to count or look things up by key, and a set to remove duplicates or test membership quickly.
Counting the words in
the cat and the dog and the birdfinds 'the' three times, 'and' twice, and each of the other three words once.
You want to know how many times each word appears in a sentence. You could keep a list of words and count by hand, but there is a tool made for the job. Python has three main containers, and counting words is a good test of when to reach for which.
The idea in plain words
A list is an ordered collection. You access items by position (starting at 0), the same item can appear more than once, and you can change it.
A dictionary (
dict) stores pairs of a key and a value. You look up a value by its key, not its position, and each key appears once.A set is an unordered collection of unique items. Adding something that is already there does nothing.
names = ["Ava", "Ben", "Ava"] # list: order kept, duplicates kept
ages = {"Ava": 15, "Ben": 14} # dict: look up by key
unique = {"Ava", "Ben", "Ava"} # set: duplicates collapseThe set unique has just two members, Ava and Ben. Looking up ages['Ava'] gives 15 directly, without searching through the pairs one by one.
Why lookups differ
To find an item in a list, Python checks the items one at a time until it finds a match, so a longer list takes longer. A dictionary or set uses the item's hash, a number computed from it, to jump close to where it is stored. Checking whether something is in a set stays fast even when the set is large. That is the main reason to use them.
Worked example: counting words in a sentence
sentence = "the cat and the dog and the bird"
words = sentence.split()
print(words)
counts = {}
for w in words:
counts[w] = counts.get(w, 0) + 1
print(counts)
print(len(words))
print(len(set(words)))Trace it.
split()breaks the sentence at spaces and returns a list:['the', 'cat', 'and', 'the', 'dog', 'and', 'the', 'bird']. That is 8 words.countsstarts as an empty dictionary.For each word,
counts.get(w, 0)returns the current count, or 0 if the word is new. Adding 1 and storing it back updates the dictionary.After the loop the counts are 3 for the, 1 for cat, 2 for and, 1 for dog and 1 for bird.
len(set(words))removes duplicates first, leaving five distinct words.
The program prints the list, then {'the': 3, 'cat': 1, 'and': 2, 'dog': 1, 'bird': 1}, then 8, then 5.
How to check your answer
The counts must add up to the number of words:
3 + 1 + 2 + 1 + 1 = 8.The number of keys must equal the number of distinct words: 5.
Spot-check one word by counting it by hand. 'the' appears three times.
Try a sentence with different capital letters. 'The' and 'the' are different keys unless you lower-case first.
Duplicates: set or dictionary?
Say you want the distinct words but in the order they first appeared. A set would lose the order. A dictionary keeps it, so you can use its keys.
words = ["the", "cat", "and", "the", "dog", "and", "the", "bird"]
distinct = list(dict.fromkeys(words))
print(distinct)This prints ['the', 'cat', 'and', 'dog', 'bird']. Each word is stored as a key the first time it is seen, later copies are ignored, and the keys stay in insertion order. If the order does not matter, set(words) is simpler.
The most useful operations
A few moves cover most everyday use. For a list:
nums = [10, 20, 30]
print(nums[0]) # 10, the first item
print(nums[-1]) # 30, the last item
nums.append(40)
print(nums[1:3]) # [20, 30], items at positions 1 and 2The slice nums[1:3] starts at position 1 and stops before position 3, so it returns two items. Sets also support maths-style operations:
a = {1, 2, 3}
b = {2, 3, 4}
print(a & b) # in both: {2, 3}
print(a | b) # in either: {1, 2, 3, 4}
print(a - b) # in a but not b: {1}These are useful for questions like which students are in both clubs, or which words appear in one text but not another. For plain data you could do it with loops, but the set operators say what you mean in one line.
Combining containers
Real data often nests one container inside another. A list of dictionaries is a natural way to hold a table of records, one dictionary per row.
students = [
{"name": "Ava", "grade": 9},
{"name": "Ben", "grade": 10},
]
for s in students:
print(s["name"], s["grade"])This prints Ava 9 and then Ben 10. Each pass of the loop gets one dictionary, and the key picks the field you want. A dictionary whose values are lists works the other way round, for example mapping each club name to the list of its members. The shape you choose should match the question you will ask most often.
Choosing between them
Need | Use | Why |
|---|---|---|
Keep things in order, allow repeats | list | Position matters |
Find a value by a name | dict | Fast lookup by key |
Remove duplicates | set | Each item stored once |
Check membership quickly | set or dict | Constant-time on average |
Common mistakes
Using a list when you keep searching it for items. A set or dictionary is faster.
Expecting a set to keep order. It does not guarantee any.
Using
{}for an empty set. That makes an empty dictionary. Useset().Asking for a missing key with
counts['fish'], which raises aKeyError. Use.get()with a default.Changing a list while you loop over it.
Where you will use it next
These three containers carry most real programs: counting, grouping, caching and checking for duplicates. The dictionary's fast lookup is explained in hash tables and why lookups are fast. When code that uses them misbehaves, debugging a program methodically is the place to start.
Frequently asked questions
Can a dictionary key be a list?
No. Keys must be hashable, which means unchangeable types such as strings, numbers and tuples.
Do dictionaries keep order?
In modern Python they keep the order in which keys were inserted. Sets do not guarantee any order.
