# Python hash() Function

Rate this post

Python’s built-in `hash(object)` function takes one object as an argument and returns its hash value. 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.

## Learn Python hash() by Example

The basic example shows the hash value of an integer is the integer itself:

```>>> hash(42)
42```

However, the hash value of a string is completely unpredictable—at least for you without knowing the underlying implementation of the h`ash()` function:

```>>> hash('42')
-7286207279771019371```

Hash values of floats are either the converted integer where this conversion doesn’t lose any information, or a random integer where the float has a non-zero fractional value:

```>>> hash(42.0)
42
>>> hash(42.1)
230584300921372714```

You can also calculate hash values of tuples and other immutable collection types. The resulting `hash()` value is a combination of the `hash()` values inside the immutable collection.

```>>> hash((1, 2, 3))
2528502973977326415```

However, you cannot calculate the `hash()` value of mutable collection types such as lists, sets, and dictionaries because this would mean that each modification of the collection would have to modify the hash value. This is impossible because hash values must be static for the same object. That’s why Python throws an error if you try to calculate the hash value of a mutable collection type.

Unhashable list:

```>>> hash([1, 2, 3])
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
hash([1, 2, 3])
TypeError: unhashable type: 'list'```

Unhashable set:

```>>> hash({1, 2, 3})
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
hash({1, 2, 3})
TypeError: unhashable type: 'set'```

Unhashable dict:

```>>> hash({'Alice': 18, 'Bob': 19})
Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
hash({'Alice': 18, 'Bob': 19})
TypeError: unhashable type: 'dict'```

## Python hash() Video

But before we move on, I’m excited to present you my new Python book Python One-Liners (Amazon Link).

If you like one-liners, you’ll LOVE the book. It’ll teach you everything there is to know about a single line of Python code. But it’s also an introduction to computer science, data science, machine learning, and algorithms. The universe in a single line of Python!

The book was released in 2020 with the world-class programming book publisher NoStarch Press (San Francisco).

## Implementing Python hash() for Custom Objects

What if you define your own class—how to modify the computation of the `hash()` value?

For example, say you create a class Customer that has one value, the customer’s value for your company:

```class Customer:
def __init__(self, value):
self.value = value

alice = Customer(1000)
bob = Customer(1000)

print('Alice Hash Value:', hash(alice))
print('Bob Hash Value:', hash(bob))```

The output may be the following two hash values:

```Alice Hash Value: -9223371944682613630
Bob Hash Value: 92172188494```

The problem with this is that both should have the same hash value as they should be considered equal. So, how can you modify the output of the `hash()` function on a custom object?

Internally, Python calls the `object.__hash__()` dunder method to calculate the `hash(object)` value. The only thing for you to do is to overwrite its behavior. You can calculate the hash value of the custom object as a combination of the hash value of its attributes using `hash()` function calls on those!

```
class Customer:
def __init__(self, value):
self.value = value

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

alice = Customer(1000)
bob = Customer(1000)
print('Alice Hash Value:', hash(alice))
print('Bob Hash Value:', hash(bob))
```

The hash value of a Customer object now is the hash value of the associated integer attribute `value`:

```Alice Hash Value: 1000
Bob Hash Value: 1000```

Both objects have the same hash value now!

## Can Different Objects Have the Same Hash Value?

As the hash value is calculated based on the object’s data, two different but equal objects must have the same hash value. In the following example, we create two tuple objects with the same content. But they’re still different objects as proven by the call `t1 is t2` which results in `False`.

```>>> t1 = (1, 2)
>>> t2 = (1, 2)
>>> t1 is t2
False```

However, the `hash()` value of both is the same!

```>>> hash(t1)
3713081631934410656
>>> hash(t2)
3713081631934410656
>>> hash(t1) == hash(t2)
True```

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.

## Relationship __eq__() and __hash__()

Note that it is a good practice and avoids many subsequent problems to also implement the `__eq__()` method when overwriting `__hash__()`. Otherwise, two objects with the same hash value can still be considered different when using the `==` comparison. This would be illogical because the same hash value indicates that they’re considered equal!

```# BAD PRACTICE
# (no __eq__ method)
class Customer:
def __init__(self, value):
self.value = value

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

alice = Customer(1000)
bob = Customer(1000)
print('Alice Hash Value:', hash(alice))
print('Bob Hash Value:', hash(bob))
print('Are they equal?', bob == alice)```

The inconsistent output indicates that although Alice and Bob have the same hash value, they’re still considered unequal.

```Alice Hash Value: 1000
Bob Hash Value: 1000
Are they equal? False```

Instead, the correct example would be the following where the `__eq__` method is overwritten.

```# GOOD PRACTICE
# (defined __eq__ method)
class Customer:
def __init__(self, value):
self.value = value

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

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

alice = Customer(1000)
bob = Customer(1000)
print('Alice Hash Value:', hash(alice))
print('Bob Hash Value:', hash(bob))
print('Are they equal?', bob == alice)
```

Now, the output is more consistent:

```Alice Hash Value: 1000
Bob Hash Value: 1000
Are they equal? True```

## Summary

Python’s built-in `hash(object)` function takes one object as an argument and returns its hash value.

```>>> hash(42)
42```

As the hash value is calculated based on the object’s data, two different but equal objects must have the same hash value.

```>>> t1 = (1, 2)
>>> t2 = (1, 2)
>>> hash(t1)
3713081631934410656
>>> hash(t2)
3713081631934410656
>>> hash(t1) == hash(t2)
True
>>> t1 is t2
False```

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.

## 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! 