Search code examples
pythondictionarykeyerror

KeyError thrown even if hashes are the same


I'm trying to get a value from the dictionary using a key - a hashable object. Unfortunately I get a KeyError even if the key with the same hash exists in the dictionary:

#structures.py
class TransactionDesignation:
    def __init__(self, gd, id, child_of):
        self.id = id
        self.child_of = child_of 
        self.gd = gd

    def __key(self):
        return (self.id, self.child_of, self.gd)

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

    def __eq__(self, other):
        return self.id == other.id and self.child_of == other.child_of and self.gd == other.gd

    def __str__(self):
        return "Transaction id='{}', childOf='{}', gd='{}', hash='{}'".format(self.id, self.child_of, self.gd, self.__hash__())

#main.py

#TRANSACTIONS is some enum value
logs[TRANSACTIONS] = {}
...
transaction_designation = TransactionDesignation(gd, id, child_of)
#Transaction is added to the logs dictionary with the key transaction_designation 
...
last_finished_transaction_designation = transaction_designation
print("Transactions:")
for key, value in logs[TRANSACTIONS].items():
   print(str(key))

print("Last finished transaction:")
print(str(last_finished_transaction_designation))
print(last_finished_transaction_designation in logs[TRANSACTIONS])

transaction = logs[TRANSACTIONS][last_finished_transaction_designation]

returns

Transactions:
...
Transaction id='3916', childOf='3317', gd='test1', hash='-4959730785004793724'
Transaction id='3917', childOf='3318', gd='test1', hash='-7583793915122604655'
Last finished transaction:
Transaction id='3917', childOf='3318', gd='test1', hash='-7583793915122604655'
False

    transaction = logs[TRANSACTIONS][last_finished_transaction_designation]
KeyError: <structures.TransactionDesignation object at 0x7fdd6145f3a0>

Any ideas why this key couldn't be found in the dictionary? Hashes are identical, but still there is the KeyError visible.

[Edit]

I checked the addresses of last_finished_transaction_designation and the key of the last saved position in the dictionary and they are the same.


Solution

  • I made a mistake during implementation of this mechanism. @Jasonharper, I was wrong saying no more code is needed. The problem is here:

    transaction_designation = TransactionDesignation('test1', '3917', None)
    logs[TRANSACTIONS][transaction_designation] = transaction
    #...
    transaction_designation.child_of = '3318'
    last_finished_transaction_designation = transaction_designation
    

    I changed the key without thinking it is actually prohibited. After changing it, I wasn't able to get this transaction either by old or by new key. Keys should be unchanged.

    Solution:

    transaction_designation = TransactionDesignation('test1', '3917', None)
    logs[TRANSACTIONS][transaction_designation] = transaction
    #...
    transaction = logs[TRANSACTIONS].pop(transaction_designation)
    transaction_designation.child_of = '3318'
    logs[TRANSACTIONS][transaction_designation] = transaction
    
    last_finished_transaction_designation = transaction_designation
    

    With such implementation nothing goes wrong.