Can I trick you to believe that Python dictionaries can have non-unique keys?

Understand how Python objects behave as hashed dictionary keys.

Photo by Cody Nottingham on Unsplash
{'Apple': 1, 'Apple': 2, 'Apple': 3}

Keys have to be hashable

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}

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

Keys have to unique

class Fruit:

def __hash__(self):
return 1

def __eq__(self, other):
return True

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

# This time, printing d gives us the following
# {<__main__.Fruit at 0x10873ed50>: 2}
class Fruit:

def __init__(self, name):
self.name = name

def __hash__(self):
return hash(self.name)

def __eq__(self, other):
return self.name == other.name

d = {
Fruit("Apple"): 1,
Fruit("Orange"): 2,
Fruit("Apple"): 3
}

# This time, printing d gives us the following
# {<__main__.Fruit at 0x10873cb90>: 3, <__main__.Fruit at 0x108247ad0>: 2}

Dressing the keys up

class Fruit:

def __init__(self, name):
self.name = name

def __hash__(self):
return hash(self.name)

def __eq__(self, other):
return self.name == other.name

def __repr__(self):
return f"'{self.name}'"

d = {
Fruit("Apple"): 1,
Fruit("Orange"): 2,
Fruit("Apple"): 3
}

# And now, printing d gives us the following
# {'Apple': 3, 'Orange': 2}
class Fruit:

def __init__(self, name):
self.name = name

def __hash__(self):
return hash(self.name)

def __eq__(self, other):
return self.name == other.name

def __repr__(self):
return "'Apple'"

d = {
Fruit("Apple"): 1,
Fruit("Orange"): 2,
Fruit("Banana"): 3
}

# And now, printing d gives us the following
# {'Apple': 1, 'Apple': 2, 'Apple': 3}
d['Apple']

“User-defined classes have __eq__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y)”. [Python docs]

class Fruit:

def __init__(self, name):
self.name = name

def __hash__(self):
return hash(self.name)

def __eq__(self, other):
return self.name == other.name

def __repr__(self):
return self.name

apple = Fruit("Apple")
orange = Fruit("Orange")

d = {
apple: 1,
orange: 2,
}
apple.name = "banana"
d[apple]

# This will complain raising a KeyError
# KeyError: banana

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
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.