Here below when I try to hash a list, it gives me an error but works with a tuple. Guess it has something to do with immutability. Can someone explain this in detail ?
List
x = [1,2,3] y = {x: 9} Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list'
Tuple
z = (5,6) y = {z: 89} print(y) {(5, 6): 89}
This error occurs when trying to hash a list, which is an unhashable object. For example, using a list as a key in a Python dictionary will cause this error since dictionaries only accept hashable data types as a key. The standard way to solve this issue is to cast a list to a tuple, which is a hashable data type.
All immutable built-in objects in Python are hashable like tuples while the mutable containers like lists and dictionaries are not hashable. Objects which are instances of the user-defined class are hashable by default, they all compare unequal, and their hash value is their id().
In Python, any immutable object (such as an integer, boolean, string, tuple) is hashable, meaning its value does not change during its lifetime. This allows Python to create a unique hash value to identify it, which can be used by dictionaries to track unique keys and sets to track unique values.
Just use a tuple as a key. Tuples are immutable and hashable, so they're useful as dictionary keys. list_of_ints = [1, 20, 3, 4] # tuple(list_of_ints) == (1, 20, 3, 4) some_dict = {tuple(list_of_ints): "some value", ...}
Dicts and other objects use hashes to store and retrieve items really quickly. The mechanics of this all happens "under the covers" - you as the programmer don't need to do anything and Python handles it all internally. The basic idea is that when you create a dictionary with {key: value}
, Python needs to be able to hash whatever you used for key
so it can store and look up the value quickly.
Immutable objects, or objects that can't be altered, are hashable. They have a single unique value that never changes, so python can "hash" that value and use it to look up dictionary values efficiently. Objects that fall into this category include strings, tuples, integers and so on. You may think, "But I can change a string! I just go mystr = mystr + 'foo'
," but in fact what this does is create a new string instance and assigns it to mystr
. It doesn't modify the existing instance. Immutable objects never change, so you can always be sure that when you generate a hash for an immutable object, looking up the object by its hash will always return the same object you started with, and not a modified version.
You can try this for yourself: hash("mystring")
, hash(('foo', 'bar'))
, hash(1)
Mutable objects, or objects that can be modified, aren't hashable. A list can be modified in-place: mylist.append('bar')
or mylist.pop(0)
. You can't safely hash a mutable object because you can't guarantee that the object hasn't changed since you last saw it. You'll find that list
, set
, and other mutable types don't have a __hash__()
method. Because of this, you can't use mutable objects as dictionary keys:
>>> hash([1,2,3]) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list'
Eric Duminil's answer provides a great example of the unexpected behaviour that arises from using mutable objects as dictionary keys
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With