Skip to content Skip to sidebar Skip to footer

Python Dictionary Doesn't Have All The Keys Assigned, Or Items

I created the following dictionary exDict = {True: 0, False: 1, 1: 'a', 2: 'b'} and when I print exDict.keys(), well, it gives me a generator. Ok, so I coerce it to a list, and i

Solution 1:

This happens because True == 1 (and False == 0, but you didn't have 0 as a key). You'll have to refactor your code or data somehow, because a dict considers keys to be the same if they are "equal" (rather than is).

Solution 2:

What you are seeing is python coercing the 1 to be equal to the True.

You'll see that the dictionary you print is:

False  1
True   a2b

Where the value a was meant to be assigned to the 1, but instead the value for True got reassigned to a.

According to the Python 3 Documentation:

The Boolean type is a subtype of the integer type, and Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the exception being that when converted to a string, the strings "False" or "True" are returned, respectively.

Emphasis mine.

Note: In python 2.X True and False can be re-assigned, so this behavior cannot be guaranteed.

Solution 3:

Python take the 1 as True. And the Boolean type is a subtype of the integer type

In [1]: a = {}

In [2]: a[True] = 0

In [3]: 1 in a.keys()
Out[3]: True

Solution 4:

If you insert a key-value pair in a dict python checks if the key already exists and if it exists it will replace the current value.

This check does something like this:

defhash_and_value_equal(key1, key2):
    returnhash(key1) == hash(key2) and key1 == key2

So not only must the values be equal but also their hash. Unfortunatly for you True and 1 but also False and 0 will be considered equal keys:

>>> hash_and_value_equal(0, False)
True>>> hash_and_value_equal(1, True)
True

and therefore they replace the value (but not the key):

>>>a = {1: 0}>>>a[True] = 2>>>a
{1: 2}

>>>a = {False: 0}>>>a[0] = 2>>>a
{False: 2}

I've showed the case of adding a key manually but the steps taken are the same when using the dict literal:

>>>a = {False: 0, 0: 2}>>>a
{False: 2}

or the dict-builtin:

>>>a = dict(((0, 0), (False, 2)))>>>a
{0: 2}

This can be very important if you write own classes and want to use them as potential keys inside dictionaries. Depending on your implementation of __eq__ and __hash__ these will and won't replace the values of equal but not identical keys:

classIntContainer(object):
    def__init__(self, value):
        self.value = value

    def__eq__(self, other):
        return self.value == other

    def__hash__(self):
        # Just offsetting the hash is enough because it also checks equalityreturnhash(1 + self.value)

>>> hash_equal(1, IntContainer(1))
False>>> hash_equal(2, IntContainer(1))
False

So these won't replace existing integer keys:

>>>a = {1: 2, IntContainer(1): 3, 2: 4}>>>a
{1: 2, <__main__.IntContainer at 0x1ee1258fe80>: 3, 2: 4}

or something that is considered as identical key:

classAnotherIntContainer(IntContainer):
    def__hash__(self):
        # Not offsetted hash (collides with integer)returnhash(self.value)

>>> hash_and_value_equal(1, AnotherIntContainer(1))
True

These will now replace the integer keys:

>>>a = {1: 2, AnotherIntContainer(1): 5}>>>a
{1: 5}

The only really important thing is to keep in mind that dictionary keys are consered equal if the objects and their hash is equal.

Post a Comment for "Python Dictionary Doesn't Have All The Keys Assigned, Or Items"