Search code examples
pythonpython-3.xdictionaryhashcpython

Strange behavior with python dictionary


I was learning about python hash function and came across the following behavior.

>>> hash(-1)
-2
>>> hash(-2)
-2

SO already has a great post which answers why: Why do -1 and -2 both hash to -2 in CPython?

Since python dictionary uses hash of the key to store the value, the following output is expected because both True and 1 has same hash:

>>> my_dict = { True: "true", 1: "one"}
>>> my_dict
{True: 'one'}
>>> hash(True)
1
>>> hash(1)
1

But if I try with the following, I expect the output as { -1: "Minus Two"}, since -1 and -2 has same hash. But that was not the case.

>>> my_dict = { -1: "Minus One", -2: "Minus Two"}
>>> my_dict
{-1: 'Minus One', -2: 'Minus Two'}
>>> hash(-1)
-2
>>> hash(-2)
-2

What is the reason for this behavior?. Don't dictionaries use the hash of the key to store it's value?

NOTE: I know it's CPython specific, but I'm curious to know the reason for this behavior.


Solution

  • Not only does it check the hash value of an object, it also checks the equality of it. You can see this in effect with this example:

    >>> class Samesies:
    ...     def __hash__(self):
    ...             return 1
    ...     def __eq__(self, other):
    ...             return True
    ...
    >>> {Samesies(): 1, Samesies(): 2}
    {<__main__.Samesies object at 0x0000023997ACEFA0>: 2}
    

    EDIT: The reason that 1 == True and hash(1) == hash(True) is due to the fact that bool actually subclasses int.