Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What makes a user-defined class unhashable?

The docs say that a class is hashable as long as it defines __hash__ method and __eq__ method. However:

class X(list):   # read-only interface of `tuple` and `list` should be the same, so reuse tuple.__hash__   __hash__ = tuple.__hash__  x1 = X() s = {x1} # TypeError: unhashable type: 'X' 

What makes X unhashable?

Note that I must have identical lists (in terms of regular equality) to be hashed to the same value; otherwise, I will violate this requirement on hash functions:

The only required property is that objects which compare equal have the same hash value

The docs do warn that a hashable object shouldn't be modified during its lifetime, and of course I don't modify instances of X after creation. Of course, the interpreter won't check that anyway.

like image 498
max Avatar asked Apr 20 '12 22:04

max


People also ask

What does Unhashable type mean in Python?

TypeError: unhashable type: 'list' usually means that you are trying to use a list as an hash argument. This means that when you try to hash an unhashable object it will result an error. For ex. when you use a list as a key in the dictionary , this cannot be done because lists can't be hashed.

What does it mean to be Unhashable type?

Unhashable type errors appear in a Python program when a data type that is not hashable is used in code that requires hashable data. An example of this is using an element in a set or a list as the key of a dictionary.

Are User Defined objects hashable in Python?

From the Python3 docs circa 5 March 2021: Objects which are instances of user-defined classes are hashable by default. They all compare unequal (except with themselves), and their hash value is derived from their id().

Why list is Unhashable and tuple is hashable?

Because a list is mutable, while a tuple is not. When you store the hash of a value in, for example, a dict, if the object changes, the stored hash value won't find out, so it will remain the same.


1 Answers

Simply setting the __hash__ method to that of the tuple class is not enough. You haven't actually told it how to hash any differently. tuples are hashable because they are immutable. If you really wanted to make you specific example work, it might be like this:

class X2(list):     def __hash__(self):         return hash(tuple(self)) 

In this case you are actually defining how to hash your custom list subclass. You just have to define exactly how it can generate a hash. You can hash on whatever you want, as opposed to using the tuple's hashing method:

def __hash__(self):     return hash("foobar"*len(self)) 
like image 95
jdi Avatar answered Oct 18 '22 05:10

jdi