2010-03-28 2 views
25

У меня есть список объектов, которые я хочу превратить в набор. Мои объекты содержат несколько полей, некоторые из которых являются o.id и o.area. Я хочу, чтобы два объекта были равны, если эти два поля одинаковы. т.е.: o1==o2 если и только если o1.area==o2.area and o1.id==o2.id.Python: Как работает набор

Я пробовал переписывать __eq__ и __cmp__, но я получаю ошибку: TypeError: unhashable instance.

Что я должен переписать?

+3

http://docs.python.org/library/stdtypes.html#set-types-set-frozenset и http://docs.python.org/glossary.html#term-hashable –

ответ

38

Определите метод __hash__ для возврата значимого хэша на основе полей id и area. Например:

def __hash__(self): 
    return hash(self.id)^hash(self.area) 
+13

Я немного поразрядная побитовая математика на чем-то подобном. Я бы использовал что-то вроде = return hash ((self.id, self.area)) =. –

+1

Это может быть проблемой при хешировании двух аналогичных компонентов. Например, hash (x)^hash (y) будет ошибочным, если пары координат с обведенными осями являются общими. В этом случае это крайне маловероятно, чтобы вызвать проблемы, поскольку невозможно генерировать ints и строки с коррелированными хэшами. Сказав это, ваше предложение по-прежнему остается хорошим, о чем я бы хотел подумать :-). –

9

"Тип: Устранение неполадок". ошибка, вероятно, связано то есть определения класса старого стиля .:

class A: 
    pass 

Использовать новый стиль вместо:

class A(object): 
    pass 

Если переопределить __cmp__ функцию, которую вы должны переопределение __hash__ за использование объекта в наборах. В другом случае хеш рассматривает все экземпляры объектов как неравные, а функция __cmp__ никогда не будет вызвана.

Смежные вопросы