2010-03-28 7 views
25

Mam listę obiektów, które chcę zamienić w zestaw. Moje obiekty zawierają kilka pól, z których niektóre są o.id i. Chcę, aby dwa obiekty były równe, jeśli te dwa pola są takie same. tj: o1==o2 tylko wtedy, gdy o1.area==o2.area and o1.id==o2.id.Python: Jak działają zestawy

Próbowałem nadpisać __eq__ i __cmp__, ale pojawia się błąd: TypeError: unhashable instance.

Co mam przepisać?

+3

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

Odpowiedz

38

Należy zdefiniować metodę zwracania znaczącego skrótu na podstawie pól identyfikatora i obszaru, używając metody __hash__. Np .:

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

Jestem trochę nieporadny z matematyki na coś takiego. Użyłbym czegoś takiego jak = return hash ((self.id, self.area)) =. –

+1

Jest to prawdopodobnie problem podczas mieszania dwóch podobnych komponentów. Na przykład hash (x)^hash (y) źle się zachowuje, jeśli para współrzędnych z wymienionymi osiami jest wspólna. W tym przypadku jest bardzo mało prawdopodobne, aby powodować problemy, ponieważ niemożliwe jest generowanie int i stringów ze skorelowanymi hashe. Mimo to twoja sugestia jest nadal dobra, o czym chciałbym pomyśleć :-). –

9

"TypeError: Unhashable instance." Błąd jest prawdopodobnie ze względu na starym stylu definicji klasy I.E .:

class A: 
    pass 

Zastosowanie nowego stylu zamiast:

class A(object): 
    pass 

Jeśli zastąpić __cmp__ funkcję powinien przesłanianie __hash__ za korzystanie z obiektu w zestawach. W innym przypadku funkcja hash traktuje wszystkie instancje obiektów jako nierówne, a funkcja __cmp__ nigdy nie będzie wywoływana.