Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Python, why is a tuple hashable but not a list?

Tags:

python

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} 
like image 819
Nagendra Kakarla Avatar asked Feb 13 '17 12:02

Nagendra Kakarla


People also ask

Why lists are not hashable in Python?

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.

Why is tuple hashable Python?

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().

What does it mean that tuples are hashable?

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.

How do you make a list hashable in Python?

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", ...}


1 Answers

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

like image 55
daveruinseverything Avatar answered Sep 29 '22 17:09

daveruinseverything