Python Part I · Module 8 · Dictionaries
Dictionaries or Lists: Which to Use
Both of these structures hold several things, both can grow, and both can be walked through. Asked which is better, there is no answer — asked how you intend to find the data again, there usually is one immediately. A list remembers the order things came in and lets you reach the third one. A dictionary forgets nothing about which name goes with which value and lets you ask for the one you want by that name. Almost every real decision between them is settled by that difference, and the chapters you have just finished supply the evidence: the operations each structure offers are not arbitrary feature lists but consequences of what it is organised around.
Foundation13 min readPythonPart IFundamentalsDictionariesDesign
Part I · Module 8 · Chapter 8.8 · Dictionaries or Lists: Which to Use
1. Two Shapes for Test Names
order = ["smoke", "reset"]
status = {"smoke": "PASS", "reset": "FAIL"}
print(len(order))
print(len(status))2
2Both hold two test names, and they are not alternatives for the same job.
order is the sequence tests run in. smoke is first because it runs first, and that is the entire content — there is no "value" attached to a test name here, only its place in the queue.
status is one outcome per test. There is no first test and no queue; there is a name and what happened to it.
2. The One Question
How will you look this up again?
If the answer involves where it is — the first one, the next one, the order they came in — that is a list.
If the answer involves what it is called — the status of reset, the width of clk — that is a dictionary.
3. What Each One Can Answer
The capabilities follow from the organising principle rather than being arbitrary.
A list has positions, so it can answer questions about place:
order = ["smoke", "reset"]
print(order[0])
print(order[-1])
print(order.index("reset"))smoke
reset
1The first, the last, and where a given name sits. A dictionary can answer none of those — Chapter 8.1 showed d[0] is KeyError: 0, because 0 is read as a key.
A dictionary has keys, so it can answer questions about association:
status = {"smoke": "PASS", "reset": "FAIL"}
print(status["reset"])FAILA list cannot do that at all without searching.
The membership comparison
Both support in, and this is where the difference is sharpest:
order = ["smoke", "reset"]
status = {"smoke": "PASS", "reset": "FAIL"}
print("smoke" in order)
print("smoke" in status)
print("PASS" in status)
print("PASS" in status.values())True
True
False
TrueFour lines, one operator, four different questions:
"smoke" in order— is this an element of the list?"smoke" in status— is this a key?"PASS" in status— is this a key? No — and"PASS"is a value, so the answer isFalse."PASS" in status.values()— is this a value? Yes.
The third line is Chapter 8.3's rule arriving where it does the most damage: a reader comparing the two structures assumes in means the same thing on both, and it does not.
Duplicates
l = ["smoke", "reset", "smoke"]
d = {"smoke": "PASS", "reset": "FAIL", "smoke": "SKIP"}
print(len(l), len(d))3 2The list kept all three; the dictionary has two entries, because the repeated key replaced the first value — Chapter 8.2's rule.
That is a design consideration, not a quirk. If a test can appear twice and both appearances matter, a dictionary keyed by test name will silently lose one.
4. The Same Data, Both Ways
Pairs of names and outcomes can be held either way:
pairs = [("smoke", "PASS"), ("reset", "FAIL")]
table = {"smoke": "PASS", "reset": "FAIL"}
print(pairs[1][1])
print(table["reset"])FAIL
FAILSame answer, two routes. pairs[1][1] says the second pair, its second field — and you had to know that reset is second. table["reset"] says what it means.
And they convert in both directions:
pairs = [("smoke", "PASS"), ("reset", "FAIL")]
table = {"smoke": "PASS", "reset": "FAIL"}
print(dict(pairs))
print(list(table.items())){'smoke': 'PASS', 'reset': 'FAIL'}
[('smoke', 'PASS'), ('reset', 'FAIL')]Chapter 8.6's dict(pairs) and Chapter 8.5's .items(), which is why the list-of-tuples shape from Chapter 6.7 keeps appearing — it is the sequence form of the same information.
5. Records: a List of Them, or a Dictionary of Them
For nested data the same question applies one level up:
as_list = [{"test": "smoke", "status": "PASS"}, {"test": "reset", "status": "FAIL"}]
as_dict = {"smoke": {"status": "PASS"}, "reset": {"status": "FAIL"}}
print(len(as_list), len(as_dict))
print(as_list[0]["status"])
print(as_dict["smoke"]["status"])2 2
PASS
PASSThe list version keeps the records in order and repeats the test name inside each one. The dictionary version uses the test name as the key and does not store it twice.
Choose by the same question: if you will process them in order, the list is right; if you will ask about a named test, the dictionary is. Chapter 8.7 covers reading either.
6. Reasons That Are Not the Reason
Two arguments come up and neither should decide the choice.
"Dictionaries are faster." There is a real difference in one specific place: finding something by name. A dictionary goes more or less straight to it, for the reason Chapter 7.2 gave about hashing; a list has to look through its elements. For ten items that is irrelevant. For ten thousand items looked up repeatedly it is the difference between a script that finishes and one that does not.
But notice what that actually says. It is not "dictionaries are faster" — it is "looking something up by name is what a dictionary is for", which is the same sentence as Section 2. The speed is a consequence of using the right structure, not an independent reason to pick one.
"Dictionaries are more modern / more Pythonic." Not a reason. A queue of jobs is a list in any language and any era.
7. Side by Side
Now that each point has been demonstrated:
| list | dict | |
|---|---|---|
| Found by | position | key |
| Order | kept, and meaningful | insertion order kept, not used for lookup |
| Repeats | kept as separate items | a repeated key replaces |
x[0] | the first element | KeyError: 0 |
x["name"] | TypeError | the mapped value |
v in x | is it an element? | is it a key? |
.index(v) | yes | no |
len() counts | items | entries |
Both are mutable, and both preserve the order things were added — so neither mutability nor order is what separates them. Lookup is.
8. Predict, Run, Observe
Predict every line before reading on.
suite = ["smoke", "reset"]
status = {"smoke": "PASS", "reset": "FAIL"}
print(len(suite), len(status))
print(suite[0])
print(status["smoke"])
print("reset" in suite)
print("reset" in status)
print("FAIL" in status)
print("FAIL" in status.values())
print(suite.index("reset"))The verified output:
2 2
smoke
PASS
True
True
False
True
1Same length, and then every line after that is doing something different.
"reset" in suite and "reset" in status are both True for different reasons — an element in one case, a key in the other.
"FAIL" in status is False. It is a value, and in on a dictionary asks about keys only. The next line, against .values(), is True.
And suite.index("reset") is 1; status has no .index at all, because asking where a key sits is not a question a mapping answers.
9. Exercises
Exercise 1 — apply the question. For each, choose list or dictionary and give the one-sentence reason: (a) the order tests must run in (b) the status of each test (c) the lines of a log file (d) the bit width of each signal (e) the runtimes in the order they were measured (f) which simulator each project uses
Exercise 2 — predict. For l = ["a", "b"] and d = {"a": 1, "b": 2}, give each result; two raise:
(a) l[0] (b) d["a"] (c) d[0] (d) "a" in l (e) "a" in d (f) 1 in d (g) 1 in d.values() (h) l.index("b") (i) d.index("b")
Exercise 3 — the membership trap. Explain in three sentences why "PASS" in status is False when "PASS" is clearly in the dictionary, and give the expression that asks the question the author meant.
Exercise 4 — both ways. Express "smoke passed, reset failed" as a list of pairs and as a dictionary. Write the expression that gets reset's outcome from each, and say in one sentence which you would rather read in six months.
Exercise 5 — convert. Given pairs = [("a", 1), ("b", 2)], write the line producing the dictionary form. Given that dictionary, write the line producing the list of pairs back. Name the chapter that taught each.
Exercise 6 — when a list is still right. Give two situations where results should stay a list of pairs rather than becoming a dictionary, and explain each in one sentence.
Exercise 7 — the duplicate. A script does table[test] = status for 200 records and ends with len(table) == 173. Say what the list form would have given instead, and in one sentence which is correct — being careful not to assume.
Exercise 8 — reject the reason. A colleague converts an ordered job queue into a dictionary "because dictionary lookup is faster". Write three sentences: what breaks, why the speed claim is irrelevant here, and what question they should have asked.
10. Summary
- Ask how you will look the data up again. By position or order means a list; by a name you already hold means a dictionary.
- A list is indexed by position; a dictionary is indexed by meaning.
- A list answers
x[0],x[-1]and.index(v). A dictionary answers none of them —d[0]isKeyError: 0. - A dictionary answers
d["name"]. A list cannot without searching. inasks a different question on each: an element of the list, or a key of the dictionary."PASS" in statusisFalse;"PASS" in status.values()isTrue.- A list keeps repeats; a repeated dictionary key replaces. That silently loses data if a name can legitimately occur twice.
- The same information converts both ways —
dict(pairs)andlist(d.items()). - For records, ask the question one level up: a list of records keeps order, a dictionary of records is keyed by name.
- Speed is a consequence, not a reason. Looking something up by name is what a dictionary is for; if you are searching a list for names repeatedly, that is the signal.
- Both are mutable and both preserve insertion order — neither of those separates them. Lookup does.
One chapter remains, and it widens this question to every structure in Part I.
Where this fits
Part of the Python curriculum.
