Why we can use tuples as dictionary keys but not lists in Python

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 ^ y mixes 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.