Специальный Python dict с идентификаторами объектов - PullRequest
3 голосов
/ 28 мая 2011

Я хочу создать специальный словарь, который использует идентификаторы объектов в качестве ключей, например:

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))

Но если я запускаю следующий тест, я получаю сообщение об ошибке:

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")     

Сообщение об ошибке:

AssertionError: None != 'message'                   

Что здесь не так?

Фон:

Причиной создания такого экзотического слова является то, что я хочу хранить ошибки проверки для каждого поля объекта и избегать имен полей в виде строк: domain_object.errors[domain_object.field1] в противном случае имена полей в виде строк (domain_object.errors["field1"]) будут неправильными для рефакторинга и дополнения кода.

ΤΖΩΤΖΙΟΥ:

Я уверен, что вы ничего не получите от используя идентификаторы. obj.field1= 1; print(id(obj.field1)); obj.field1= 2; print(id(obj.field1))

Если бы я не использовал идентификаторы, ключом было бы значение переменной, а не ее адрес. Это приведет к ошибкам, если два поля будут иметь одинаковое значение:

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"

Не критично, что изменение значения переменной приведет к новому адресу, поскольку после этого результат проверки больше не действителен.

1 Ответ

4 голосов
/ 28 мая 2011

__getitem__ должен возвращать результат:

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

Без return неявное возвращаемое значение равно None, и, следовательно, oiddict[key] is None для всех ключей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...