Jake Cope
Jake Cope

Reputation: 63

Why does assinging a value to the key `True` of an dictionary overwrite the value of the key `1` in the same dictionary?

For this simple Dictionary -

the Key 1 and Value "apple" always print as "1: False"

is there a reason for this I've overlooked?

$ cat dict.py

pairs = {1: "apple",
    "orange": [2, 3, 4], 
    True: False, 
    None: "True",
}
print(pairs)

*$ python3.8 dict.py

{1: False, 'orange': [2, 3, 4], None: 'True'}

thanks

Upvotes: 3

Views: 140

Answers (1)

poke
poke

Reputation: 387507

The bool type in Python is a subtype of int where True equals the number 1 and False equals the number 0:

>>> True == 1
True
>>> False == 0
True

When the values are hashed, they also result in the respectively same value:

>>> hash(True)
1
>>> hash(1)
1
>>> hash(False)
0
>>> hash(0)
0

Now, since dictionary keys are based on hash and object equality (hash equality is used first to find possibly equal keys fast, and then they are compared through equality), two values that result in the same hash and are equal will result in the same “slot” of the dictionary.

You can also see this if you create a custom type that also has this behavior:

>>> class CustomTrue:
        def __hash__(self):
            return 1
        def __eq__(self, other):
            return other == 1

>>> pairs = {
        1: "apple",
        "orange": [2, 3, 4], 
        True: False, 
        None: "True",
    }
>>> pairs[CustomTrue()] = 'CustomTrue overwrites the value'
>>> pairs
{1: 'CustomTrue overwrites the value', 'orange': [2, 3, 4], None: 'True'}

While this explains the behavior, I do agree that it can be somewhat confusing. As such I would recommend not to use dictionary keys of different types so that you don’t run into such a situation.

Upvotes: 5

Related Questions