Python __hash__() Magic Method

Rate this post

Syntax

object.__hash__(x)

The Python __hash__() method implements the built-in hash() function. So, when you cal hash(x), Python attempts to call x.__hash__(). If the return value is not an integer or the x.__hash__() method is not defined, Python will raise a TypeError.

We call this a “Dunder Method” for Double Underscore Method” (also called “magic method”). To get a list of all dunder methods with explanation, check out our dunder cheat sheet article on this blog.

Background hash()

Python’s built-in hash(object) function takes one object as an argument and returns its hash value as an integer. You can view this hash value as a unique fingerprint of this object.

As the hash value is calculated based on the object’s data, two different but equal objects must have the same hash value. It doesn’t follow, though, that two objects with the same hash value are equal—they can have the same hash value and still be different.

Example Custom __hash__()

In the following example, you create a custom class Data and overwrite the __hash__() magic method so that it returns an integer when trying to call hash(x) on a custom Data object.

class Data:
    def __hash__(self):
        return 42


x = Data()
res = hash(x) 

print(res)
# 42

Default __hash__()

If you don’t define the __hash__() magic method, Python will return its own integer hash value because __hash__() is implemented for every Python object.

class Data:
    pass


x = Data()
res = hash(x) 

print(res)
# 42

This is the output on my computer—it will probably be different on yours because the result represents a specific memory address of the object:

116229704442

TypeError: __hash__ method should return an integer

If the Python __hash__ function doesn’t return an integer value, Python will raise the TypeError: __hash__ method should return an integer upon calling hash() on a given object. To fix this error, you need to change the return value of __hash__() to an integer value.

Consider the following code snippet where you try to return a string in the dunder method __hash__():

class Data:
    def __hash__(self):
        return 'finxter'


x = Data()
res = hash(x) 

print(res)

Running this leads to the following error message on my computer:

Traceback (most recent call last):
  File "C:\Users\xcent\Desktop\code.py", line 7, in <module>
    res = hash(x)
TypeError: __hash__ method should return an integer

Good Practices __hash__

There are some requirements that should be satisfied when implementing your own custom __hash__() method. I’ll list them here as a bullet list:

  • The return value must be an integer.
  • Objects that compare equal have the same hash value. So, if x==y, it should follow that x.__hash__() == y.__hash__(). It follows that if a class doesn’t define __eq__() to check equality, it should not implement __hash__() either.
  • The return value from x.__hash__() is truncated to 4-8 bytes when calling hash(x), so make sure you don’t accidentally lose this information. You can see that the outputs differ for huge integers here:
class Data:
    def __hash__(self):
        return 99999999999999999999999999999999999999999999999999


x = Data()
res = hash(x) 

print(res)
# 619332571178673745
  • The __hash__ method on a given object often returns the result of putting the state of the object, i.e., its attribute values, into a tuple and hashing the tuple. Here’s an example:
class Person:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex
        
    def __hash__(self):
        return hash((self.name, self.age, self.sex))


ann = Person('Ann', 23, 'w')
ann_2 = Person('Ann', 23, 'w')
alice = Person('Alice', 33, 'w')


print(hash(ann))
print(hash(ann_2))
print(hash(alice))

The output shows that the first two objects, although different instances, produce the same hash value:

5084601898576458507
5084601898576458507
-1197787602517711359

References:

Where to Go From Here?

Enough theory. Let’s get some practice!

Coders get paid six figures and more because they can solve problems more effectively using machine intelligence and automation.

To become more successful in coding, solve more real problems for real people. That’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

You build high-value coding skills by working on practical coding projects!

Do you want to stop learning with toy projects and focus on practical code projects that earn you money and solve real problems for people?

🚀 If your answer is YES!, consider becoming a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

If you just want to learn about the freelancing opportunity, feel free to watch my free webinar “How to Build Your High-Income Skill Python” and learn how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!