Is there a usecase for overriding __hash__?

327 Views Asked by At

In Python3 any class will have a default __hash__ which calculates a hash based on the member variables. I can set it (explicitly or implicitly) to None in order make the class non-hashable, which certainly has some usecases.

But are there reasons to override __hash__?

I couldn't find one.

1

There are 1 best solutions below

0
that other guy On

Yes! Any time you override __eq__, and also want to be able to use the object as the key in a set or dict. This is especially common in value types, or cases where your objects represent real world entities.

__hash__ does not hash member variables at all. For an object without __hash__ or __eq__ defined, it returns some value based on its internal pointer. If __eq__ is defined, then invoking the method will cause a TypeError.work

Consider this simple case where that default __eq__ and __hash__ behavior isn't great:

import getpass

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

def currentUser():
   return User(getpass.getuser())

me = currentUser()

passwords = {}
passwords[me] = "sw0rdfish";

This has some weird behavior: me == currentUser() is false, and passwords[currentUser()] throws a KeyError. So to try to fix it, we define an __eq__:

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

Now the me == currentUser() is true, but trying to assign the password throws a TypeError: unhashable type: 'User'. Now we've gotten to the point where we want to override __hash__:

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

And now it behaves like you'd expect any other such object to behave when you use it as a key.