Do you want to use list as a dictionary key?
You cannot. A list object is not hashable, so Python does not allow it to be used as a dictionary key.
How is hashability defined?
A hashable object must satisfy these conditions:
- Its hash value can be computed.
- Its hash value does not change during its lifetime.
- It can be compared consistently with other objects.
A list is mutable, so its contents can change after creation. A tuple is immutable, so it can be hashable if all of its elements are also hashable.
How is the hash of a tuple calculated?
High-level idea
For a tuple like:
t = (a, b, c)
Python computes:
hash(t) = combine(hash(a), hash(b), hash(c))
This is done with a rolling hash-style algorithm that mixes the hash of each element into the final result.
Simplified implementation
Here is a simplified version of the CPython idea:
def tuple_hash(t):
x = 0x345678
mult = 1000003
for item in t:
y = hash(item)
x = (x ^ y) * mult
mult += 82520 + len(t) * 2
x += 97531
if x == -1:
x = -2
return x
Key properties:
x ^ ymixes the previous hash with the new element hash- Multiplication helps spread the bits
- The multiplier changes during the loop
- The final adjustment avoids
-1, which is reserved internally in CPython
This also preserves order. If we simply added the hashes like this:
hash = hash(a) + hash(b) + hash(c)
then tuples with the same values in a different order could produce the same result.
Computing the hash of a tuple takes O(N) time, where N is the length of the tuple.
One more important detail: a tuple is hashable only if every element inside it is also hashable. For example, (1, "a") is hashable, but ([1, 2], "a") is not.