Гибкий, гибкий идентификатор в python - PullRequest
0 голосов
/ 18 ноября 2010

Я пытаюсь создать какой-нибудь хешируемый идентификатор в python; Мне нужно, чтобы идентифицировать узлы на графике. Проблема в том, что некоторые узлы имеют разные атрибуты. Если атрибуты этих узлов изображаются словарями атрибутов в значениях:

idA = {'type':'A', 'name':'a_100'}
idB = {'type':'B', 'name':'b_3', 'value':7}

Я хочу, чтобы __hash__() и __eq__() использовали пары кортежей ((key1,value1), (key2,value2), ...).

Словари были бы идеальными для этого, потому что я собираюсь проверять эти свойства довольно часто, и поиск в словаре должен быть эффективным (я использую много идентификаторов, и у каждого будет много атрибутов). Но словари не являются хэшируемыми.

Frozenset пар кортежей правильно хешируется, но будет ли он эффективен для поиска?

Если я объявляю пустой класс, а затем устанавливаю для него атрибуты, это делает то, что я хочу (возможно, используя словарь под капотом), но я не знаю, как его хешировать. Может быть, есть какой-то способ хэшировать значения его членов, используя inspect или dir()?

class identifier():
    pass
idA = identifier()
idA.type = 'A'
idA.name = 'a_100'

Если есть способ использовать хэш (и == оператор), основанный на парах кортежей (attribute, value), то это также будет делать то, что я хочу.

Или есть какой-то обходной путь, который может сделать эквивалентный тип данных, который удовлетворял бы этой аналогии типа SAT: frozenset равно set как? это к dict

Спасибо за вашу помощь.


Edit:

Это правильное направление?

class identifier(dict):
    def to_frozenset(self):
        return frozenset([(k,self[k]) for k in self])
    def __hash__(self):
        return hash(self.to_frozenset())
    def __eq__(self, rhs):
        return self.to_frozenset() == rhs.to_frozenset()
    def __ne__(self, rhs):
        return not self == rhs

Это смещает вычислительную сложность, так что быстро искать атрибут идентификатора, но медленно хэшировать идентификатор или проверять два идентификатора на равенство. Если бы был способ кешировать его хэш (и запретить изменять его словарь после кэширования), и нам было гарантировано несколько коллизий хешей типов идентификаторов (поэтому проверка на равенство была редкостью), то, возможно, это было бы хорошим решением. ? Дайте мне знать, что вы думаете!

Ответы [ 3 ]

2 голосов
/ 18 ноября 2010

Нет frozendict.Но collections.namedtuple является приближением к тому поведению, которое может вас устроить.

1 голос
/ 18 ноября 2010

Я не уверен, что это решит вашу проблему, но если вы хотите, чтобы объект был хэшируемым, вы можете реализовать его следующим образом:

class Hashable(object):
    def __hash__(self):
        return hash((self.__class__.__name__,
                     tuple(self.__dict__.items())))

Вы получите данные объекта вформат структурированного кортежа вместе с именем класса в качестве хэш-сигнатуры какого-то короля.Вы даже можете расширить dict для использования в этом классе.

1 голос
/ 18 ноября 2010

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

Что касается кеширования, вы можете вспомнить to_frozenset или его хеш. В зависимости от схемы использования запомните хеш-код, который позволяет быстро вернуться к хешированию и неравенству, и сравнивайте фрозэнсеты только в случае совпадения хеш-значений.

Тем не менее, вы слишком беспокоитесь о производительности для того, кто еще не закодировал эталонный тест. Создайте простейшую возможную реализацию. Если это быстро, вы сделали. В противном случае сравните его, а затем найдите пошаговый способ улучшения результатов измерений.

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