Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Special Python dict with object IDs

I want to create a special dictionary which uses object IDs as keys, like this:

class ObjectIdDict(dict):

    def __setitem__(self, key, value):
        super(ObjectIdDict, self).__setitem__(id(key), value)

    def __getitem__(self, key):
        super(ObjectIdDict, self).__getitem__(id(key))

But if I run the following test, I get an error:

class ObjectIdDictTest(unittest.TestCase):
    def test_get_and_set(self):
        dict_to_test = ObjectIdDict()
        class Something:
            def __init__(self):
                self.x = 1
        s = Something()
        dict_to_test[s.x] = "message"
        self.assertEqual(dict_to_test[s.x], "message")     

Error message:

AssertionError: None != 'message'                   

What is wrong here?

Background:

The reason for creating such an exotic dict is that I want to store validation errors for each field of an object and want to avoid field names as strings: domain_object.errors[domain_object.field1] otherwise field names as strings (domain_object.errors["field1"]) would be bad for refactoring and code completion.

ΤΖΩΤΖΙΟΥ:

I'm certain you don't get anything by using IDs. obj.field1= 1; print(id(obj.field1)); obj.field1= 2; print(id(obj.field1))

If I would not use IDs, the key would be the value of the variable, not its address. This would lead to errors if two fields had the same value:

def test_ordinary_dict(self):
    dict_to_test = {}
    class Something:
        def __init__(self):
            self.x = 1
            self.y = 1 # same value as self.x!
    s = Something()
    dict_to_test[s.x] = "message for x"
    dict_to_test[s.y] = "message for y"
    self.assertEqual(dict_to_test[s.x], "message for x")

    # fails because dict_to_test[s.x] == dict_to_test[1] what results in:
    # "message for y"

It is not critical that changing a variables value lead to a new address since the validation result is no longer valid after that.

like image 952
deamon Avatar asked Dec 28 '25 21:12

deamon


1 Answers

__getitem__ must return the result:

def __getitem__(self, key):
  return super(ObjectIdDict, self).__getitem__(id(key))
  #^^^^^

Without a return, the implicit return value is None, and therefore oiddict[key] is None for all keys.

like image 56
phihag Avatar answered Dec 30 '25 10:12

phihag



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!