Python Dictionaries Require Hashable Keys
source link: https://alysivji.github.io/quick-hit-hashable-dict-keys.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Siv Scripts
Solving Problems Using Code
I was floored when I discovered I could use tuples (and namedtuples) as Python dictionary keys.
Turns out this is not totally correct.
Started reading Fluent Python and learned that tuples are not always immutable. For instance, they can contain list elements...
my_tuple = ('a', 'b', [1, 2])
type(my_tuple)
tuple
Let's try using my_tuple
as a dictionary key.
# First we'll create a dictionary and insert a (key, value) pair
my_dict = {}
my_dict['test'] = 'foo'
my_dict
{'test': 'foo'}
# Let's make sure that we cannot use a list element in the dictionary
my_dict[[1, 2]] = 'foo'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-3-48c007026868> in <module>() 1 # Let's make sure that we cannot use a list element in the dictionary ----> 2 my_dict[[1, 2]] = 'foo' TypeError: unhashable type: 'list'
# Dictionary has not changed
my_dict
{'test': 'foo'}
# Let's try inserting a tuple containing a list, as a key
my_dict[my_tuple] = 'bar'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-5-5c6167bc5fe6> in <module>() 1 # Let's try inserting a tuple, which contains a list, as a key ----> 2 my_dict[my_tuple] = 'bar' TypeError: unhashable type: 'list'
This should be true for namedtuples
as well.
from collections import namedtuple
TestTuple = namedtuple('TestTuple', ['field1', 'field2', 'field3'])
my_item = TestTuple('a', 'b', [1, 2])
type(my_item)
__main__.TestTuple
isinstance(my_item, tuple)
True
my_dict[my_item] = 'bar'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-8-a4dfa91fcd88> in <module>() ----> 1 my_dict[my_item] = 'bar' TypeError: unhashable type: 'list'
What's going on?
Python dictionaries leverage hash tables. When we use a key that contains an unhashable type, i.e. a list, the underlying hash map cannot guarantee the key will map to the same bucket every single time. If we can't hash our key, we can't use it in our dictionary.
Therefore, Python dictionaries require hashable dict keys. Having immutable keys is not enough.
Shoutout to Luciano Ramalho for writing Fluent Python. Only three chapters in and this kind of thinking is becoming second nature.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK