How to delude your fellow developers and have Python dictionaries with non-unique keys!

Understand how Python objects behave as hashed dictionary keys.

Tarek Amr
4 min readJan 15, 2023

--

Photo by Cody Nottingham on Unsplash

You can think of Python dictionaries as key/value pairs, where keys are required to unique.

If keys have to be unique, how could I create the following dictionary?

{'Apple': 1, 'Apple': 2, 'Apple': 3}

This is the topic of this post, but first let’s understand how dictionaries and their keys work.

Keys have to be hashable

Dictionaries are meant to speed up the lookup of a value based on its key. That’s why they use hashes, and consequently keys have to be hashable.

Let’s create our own class, that implements a __hash__() method. Thus, it is hashable, and we can use its objects as dictionary keys.

class Fruit:

def __hash__(self):
return 1

d = {
Fruit(): 1,
Fruit(): 2
}

# Printing d gives us the following
# {<__main__.Fruit at 0x10873eb10>: 1, <__main__.Fruit at 0x10873d9d0>: 2}

The __hash__() method returns a constant value, 1. I.e. both instances of Fruit have the same hash. Nevertheless, the end up being two separate keys. Why?

You probably know the following about hash functions:

Same values have the same output, but having the same output doesn’t guarantee that the inputs are the same.

The case where different values have the same hash is known as collision. Typically, a good hash function should minimize collisions. Nevertheless, collisions are still possible anyway.

That’s why Python dictionaries don’t stop at checking the hash of the objects used as keys. They probably check if the objects are equal as well. And in case of collisions, two unequal objects with equal hashes will be seen as separate keys.

Ideas for what to try next?

Keys have to unique

Let’s override the __eq__() method as well, and make sure our fruits are equal.

--

--

Tarek Amr

I write about what machines can learn from data, what humans can learn from machines, and what businesses can learn from all three.