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

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

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

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

4 ответов


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

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

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

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


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

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

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

print mydict[myinstance]

выход : Привет, мир

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

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


попробуйте реализовать хэш и эквалайзер методы в вашем классе.

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

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

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