Skip to content
VLSI Mentor

Python Part I · Module 8 · Dictionaries

Dictionaries: One Result per Test

Chapter 8.1 established what a dictionary is. This one is about writing them down and knowing the rules that govern them, and it starts by separating two shapes that look identical and mean different things. Sometimes a dictionary holds one thing described by several named fields — a single test result with its seed and its status. Sometimes it holds many things, one entry each — every test in a suite mapped to how it did. Both are ordinary dictionaries and the difference is entirely in what the keys mean. After that come the rules worth knowing before you build anything real: what happens when a key is repeated, what Python will and will not accept as a key, and why that restriction does not apply to values at all.

Foundation15 min readPythonPart IFundamentalsDictionariesConstruction

Part I · Module 8 · Chapter 8.2 · Dictionaries: One Result per Test

1. Shape One: A Record of Named Fields

One test ran, and several things are true about it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
result = {"test": "axi_smoke", "seed": 4210, "status": "FAIL", "errors": 3}
print(result)
print(len(result))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
{'test': 'axi_smoke', 'seed': 4210, 'status': 'FAIL', 'errors': 3}
4

Here the keys are field names. Each one labels a different aspect of the same thing — what it was called, what seed it used, how it finished, how many errors it produced.

This is the shape Chapter 6.1 said a tuple was for, done better. A tuple ("axi_smoke", 4210, "FAIL", 3) holds the same four values, but position 2 means "status" only because you remember that it does. Here the code says so, and Chapter 8.8 turns that into a decision.

Written across several lines it reads like the record it is:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
r2 = {
    "test": "axi_smoke",
    "status": "PASS",
}
print(r2)
print(len(r2))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
{'test': 'axi_smoke', 'status': 'PASS'}
2

The trailing comma after the last entry is allowed and worth adopting — the same convention Chapters 5.7 and 6.2 recommended, for the same reason: adding a field later stays a one-line change.

2. Shape Two: One Result per Subject

Now a different dictionary, built from the same syntax:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
results = {"smoke": "PASS", "reset": "FAIL", "crc": "PASS"}
print(len(results))
print(results["reset"])
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
3
FAIL

Here the keys are test names and every value answers the same question about a different subject. This is a results table: three tests, one outcome each.

The distinction matters most for Chapter 8.4. A record's keys are known in advance; a table's keys arrive as work proceeds.

3. The Empty Dictionary

Chapter 7.1 left a promise here. Empty braces make a dictionary, not a set:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
empty = {}
print(type(empty))
print(len(empty))
print(empty)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
<class 'dict'>
0
{}

Zero entries, type dict, and it displays as {} — the notation it owns. Contrast with the set, which has to spell itself out:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(type(set()))
print({} == set())
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
<class 'set'>
False

They are not equal and never could be; they are different kinds of collection that happen to have nothing in them.

An empty dictionary is where a results table starts. Chapter 8.4 fills one in.

4. Keys and Values Both Keep Their Own Types

A lookup gives back the value, whatever it is:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
widths = {"clk": 1, "addr": 32, "data": 64}
print(widths["addr"])
print(type(widths["addr"]))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
32
<class 'int'>

And keys are not limited to strings. Anything usable as a stable label works:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
mixed = {"name": "x", 42: "answer", ("smoke", 1234): "PASS"}
print(len(mixed))
print(mixed[42])
print(mixed[("smoke", 1234)])
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
3
answer
PASS

Three entries with three different kinds of key — a string, an integer, and a tuple. That last one is genuinely useful: Chapter 6.1 showed a (test, seed) pair being used as a key, and this is that idea in place. One test at one seed is a single identifiable thing, and a tuple names it exactly.

Section 6 says which values qualify.

5. A Repeated Key Keeps the Last Value

Keys are unique. A dictionary cannot hold two entries under the same key, and if a literal names one twice, Python does not complain:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
status = {"reset": "PASS", "reset": "FAIL"}
print(status["reset"])
print(len(status))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
FAIL
1

One entry, holding "FAIL". The second mention of "reset" did not create a second entry — it replaced the value of the first, and the earlier "PASS" is simply gone.

Note what did not happen: no error, no warning. A duplicated key in a long literal is invisible, and the only symptom is a value you did not expect.

This is the cleanest contrast with Chapter 7.1. A set enforces uniqueness on its elements. A dictionary enforces uniqueness on its keys only.

6. What May Be a Key

Chapter 7.1 established the rule for set elements, and dictionary keys follow exactly the same one: a key must be hashable.

Strings, numbers and tuples of hashable elements all qualify — Section 4 used all three. A list does not:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
d = {["smoke", 1]: "PASS"}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: unhashable type: 'list'

Nor does a set:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
d = {{"a"}: 1}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: unhashable type: 'set'

Nor does another dictionary:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
d = {{"a": 1}: 2}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: unhashable type: 'dict'

And — the case that makes the rule precise rather than approximate — nor does a tuple containing a list:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
d = {("smoke", [1, 2]): "PASS"}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: unhashable type: 'list'

That is a tuple, and it was still rejected, with list named as the offender. Chapter 6.4 explained why: a tuple fixes which values its positions refer to but does not freeze those values, so a tuple holding a list can still change underneath the dictionary that filed something under it.

7. Values Have No Restriction At All

This is where learners routinely over-apply Section 6, so it is worth being blunt: the hashability rule is about keys only.

A value can be anything, including the very things that were just rejected as keys:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
rich = {"test": "smoke", "runs": [1, 2, 3], "tags": {"fast"}}
print(rich["runs"])
print(len(rich["runs"]))
print(type(rich["tags"]))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
[1, 2, 3]
3
<class 'set'>

A list as a value and a set as a value, both perfectly legal. The dictionary never needs to find things by a value, so nothing about a value has to stay put.

8. Length and Equality

len() counts entries, regardless of what the values are:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print(len({"a": 1, "b": 1, "c": 1}))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
3

Three entries sharing one value. And equality compares the mapping, not the order it was written in:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
a = {"x": 1, "y": 2}
b = {"y": 2, "x": 1}
print(a == b)
print(a == {"x": 1})
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
True
False

The first is True — same keys mapped to the same values. The second is False, because one entry is missing. Chapter 8.1 made this point; the useful addition here is that it gives you a precise way to check a dictionary you have built: compare it against the mapping you expected.

A dictionary is never equal to another kind of collection, even one holding the same information:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
print({"a": 1} == [("a", 1)])
print({"a": 1} == {"a"})
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
False
False

Not equal to a list of pairs, and not equal to a set of its keys. Different kinds of value, as Chapters 6.1 and 7.1 established for their own types.

9. Predict, Run, Observe

Predict every line before reading on. Two are the traps from this chapter.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
d = {"smoke": "PASS", "reset": "FAIL", "smoke": "SKIP"}
print(len(d))
print(d["smoke"])
e = {"a": 1, "b": 1}
print(len(e))
print({"p": 1, "q": 2} == {"q": 2, "p": 1})
print(type({}))
print(len({}))
f = {"items": ["x", "y"]}
print(len(f))
print(len(f["items"]))

The verified output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2
SKIP
2
True
<class 'dict'>
0
1
2

len(d) is 2, not 3: "smoke" was written twice, so there are only two keys — and d["smoke"] is "SKIP", the last value given, with "PASS" discarded silently.

len(e) is 2 even though both values are 1 — values never collapse.

type({}) is dict, which is Section 3 and Module 7's deferred trap.

The last pair is the asymmetry: len(f) is 1 — one entry — while len(f["items"]) is 2, because that entry's value is a two-element list. The two len() calls are measuring different things.

10. Exercises

Exercise 1 — both shapes. Write a dictionary describing one signal with three named fields, and a separate dictionary giving the bit width of four different signals. Print the length of each and say in one sentence what the keys mean in each case.

Exercise 2 — predict the length. Without running anything, give len() for each, then verify: (a) {"a": 1, "b": 2} (b) {"a": 1, "a": 2} (c) {} (d) {"a": 1, "b": 1, "c": 1} (e) {"a": [1, 2, 3]}

Exercise 3 — the repeated key. For d = {"x": "first", "y": "mid", "x": "last"}, predict len(d) and d["x"]. Then explain in two sentences why Python raises nothing, and what symptom this bug would actually produce in a long literal.

Exercise 4 — key or not. Predict which succeed, verify all five, and state the rule in your own words: (a) {"a": 1} (b) {42: 1} (c) {("a", 1): 1} (d) {["a"]: 1} (e) {("a", ["b"]): 1}

Exercise 5 — key versus value. Explain in three sentences why {"runs": [1, 2]} is fine while {[1, 2]: "runs"} is not, referring to what a dictionary uses keys for.

Exercise 6 — the empty one. Write the two lines that prove {} creates a dictionary rather than a set, and the line that creates an empty set instead. Say in one sentence which chapter first warned you about this.

Exercise 7 — equality as a check. You build a results dictionary and want to confirm it holds exactly smoke: PASS and reset: FAIL. Write the single line that checks it, and say in one sentence why this is better than comparing printed output.

Exercise 8 — two lengths. For cfg = {"name": "axi", "flags": ["-f", "-g", "-h"]}, predict len(cfg) and len(cfg["flags"]), verify, and explain in one sentence what each number counts.

11. Summary

  • A dictionary literal is {key: value, ...}, and a trailing comma after the last entry is allowed and useful.
  • Two shapes, one structure: a record, whose keys name different aspects of one thing, and a table, whose keys name different things and grow over time.
  • {} is an empty dictionary — Module 7's deferred trap. set() is the empty set, and the two are not equal.
  • Keys may be strings, numbers or tuples — a (test, seed) tuple key names one run exactly.
  • Keys are unique. A repeated key in a literal is accepted silently and the last value wins.
  • Values are not unique. The same value may appear under any number of keys, which is what a results table looks like when everything passes.
  • A key must be hashable, not merely immutable: lists, sets, dictionaries and tuples containing them all raise TypeError: unhashable type: ....
  • Values have no restriction at all — a list or a set as a value is normal and correct.
  • Keys are how you find things; values are what you find. That asymmetry explains the whole rule.
  • len() counts entries, and equality compares the mapping, not the writing order.

You can build a dictionary and look things up in it. The next chapter is about what happens when the key is not there.

Where this fits

Part of the Python curriculum.