Python Dictionary Internals: Hashing, Collisions, O(1) Lookup and Hashable Keys
EngelhartSoftware Engineer · Technical ScreenLast updated
A Python fundamentals interview question on how dictionaries store and look up values: what gets hashed, whether different keys can share a hash, how collisions are resolved and why average lookup is constant time. It also tests whether a list can serve as a key and which objects are allowed as keys.
Explain how a Python dictionary stores and looks up values, and which objects are allowed to be dictionary keys. The questions came as a fast oral sequence in the fundamentals half of a technical screen for a junior quantitative developer role; each answer drew an immediate "why" follow-up, so the goal is precise mechanics rather than definitions.
limits = {"alpha": 100, "beta": 250}
limits["beta"] # how is this value found?
hash("beta") # what is hashed, and what is the result used for?
{[1, 2]: "x"} # what happens here, and why?
Clarifying Questions
- Should the answer describe CPython's implementation, or only the behavior the language guarantees?
- How deep should the collision discussion go: the general technique, or the exact probing scheme CPython uses?
- Do keys include instances of user-defined classes, or only built-in types?
Part 1 — How a dictionary stores and finds a value
Answer in order:
- How does a dictionary store a key-value pair, and how does it find the value for a given key?
- What does the hash function take as input, and what does the dictionary do with its output?
- Can two different keys have the same hash?
- How are hash collisions handled?
- Why is dictionary lookup O(1) on average?
What This Part Should Cover
- The path from key to hash to table slot, and the equality check that confirms a match
- Why collisions cannot be avoided, and one concrete way to resolve them
- What keeps the average cost constant, and when the cost degrades
Part 2 — Which objects can be keys
- Can a list be used as a dictionary key?
- Why not?
- Which objects can be keys?
What This Part Should Cover
- What happens when a list is used as a key, and the reason
- The rule that ties a key's hash to its equality
- Which built-in types qualify, including the tuple caveat, and how user-defined classes behave
Hints
Hint 1
From key to slot: Follow one lookup step by step: what number is computed from the key, how that number becomes a position in a table, and what still has to be checked once you reach that position.
Hint 2
Change the key after storing it: Suppose a key's contents change after it has been inserted. Where would the next lookup for it go, and what would it find there?
Follow-up questions
- A class defines `__eq__` but not `__hash__`. What happens when its instances are used as keys, and why?
- How many entries does `{1: "a", 1.0: "b", True: "c"}` contain, and what are their keys and values?
- Can crafted input make dictionary lookups slow, and what does Python do about it?
- Dictionaries have preserved insertion order since Python 3.7. How does a hash table do that without slowing lookups?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.