Могу ли я использовать объект (экземпляр класса) в качестве ключа словаря в Python?



Я хочу использовать экземпляр класса в качестве ключа словаря, например:



classinstance = class()
dictionary[classinstance] = 'hello world'


Python, кажется, не может обрабатывать классы как ключ словаря, или я ошибаюсь?
Кроме того, я мог бы использовать список кортежей, например [(classinstance, helloworld),...] вместо словаря, но это выглядит очень непрофессионально.
У вас есть какие-нибудь подсказки для решения этой проблемы?

765   4  

4 ответов:

Экземпляры должны быть hashable. Глоссарий python говорит нам:

Объект является хэшируемым, если он имеет хэш-значение, которое никогда не изменяется в течение его жизни (ему нужен метод __hash__()), и может быть сравнен с другими объектами (ему нужен метод __eq__() или __cmp__()). Хэшируемые объекты, которые сравниваются равными, должны иметь одинаковое хэш-значение.

Хэшируемость позволяет использовать объект в качестве ключа словаря и элемента набора, поскольку эти структуры данных используют хэш-значение внутренне.

Все неизменяемые встроенные объекты Python являются хэшируемыми, в то время как никакие изменяемые контейнеры (такие как списки или словари) ими не являются. Объекты, являющиеся экземплярами пользовательских классов, по умолчанию хэшируются; все они сравниваются неравномерно, и их хэш-значением является их id().

Следующий код работает хорошо, потому что по умолчанию объект класса хешируется :

Class Foo(object):
    def __init__(self):
        pass

myinstance = Foo()
mydict = {myinstance : 'Hello world'}

print mydict[myinstance]

Выход : Привет Мир

В дополнение и для более продвинутого использования, вы должны прочитать этот пост:

Объект пользовательского типа как ключ словаря

Попробуйте реализовать методы hash и eq в своем классе.

Например, вот простой хэшируемый класс словаря, который я сделал:

class hashable_dict:
    def __init__(self, d):
        self.my_dict = d
        self.my_frozenset = frozenset(d.items())
    def __getitem__(self, item):
        return self.my_dict[item]
    def __hash__(self):
        return hash(self.my_frozenset)
    def __eq__(self, rhs):
        return isinstance(rhs, hashable_dict) and self.my_frozenset == rhs.my_frozenset
    def __ne__(self, rhs):
       return not self == rhs
    def __str__(self):
        return 'hashable_dict(' + str(self.my_dict) + ')'
    def __repr__(self):
        return self.__str__()

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

Comments

    Ничего не найдено.