Co muszę zrobić, aby użyć obiektów niestandardowego typu jako kluczy w słowniku Pythona (gdzie nie chcę, aby „identyfikator obiektu” działał jako klucz), np.
class MyThing:
def __init__(self,name,location,length):
self.name = name
self.location = location
self.length = length
Chciałbym użyć MyThing jako kluczy, które są uważane za takie same, jeśli nazwa i lokalizacja są takie same. Od C # / Java jestem przyzwyczajony do przesłonięcia i podania metody equals i hashcode, i obiecuję, że nie będę mutować niczego, od czego zależy hashcode.
Co muszę zrobić w Pythonie, aby to osiągnąć? Powinienem w ogóle?
(W prostym przypadku, tak jak tutaj, być może lepiej byłoby po prostu wstawić krotkę (nazwa, lokalizacja) jako klucz - ale weź pod uwagę, że chcę, aby klucz był obiektem)
python
dictionary
Anonim
źródło
źródło
MyThing
, jeśli mają takie samename
ilocation
, aby zaindeksować słownik, aby zwrócić tę samą wartość, nawet jeśli zostały utworzone osobno jako dwa różne „obiekty”.Odpowiedzi:
Musisz dodać 2 metody , uwagę
__hash__
i__eq__
:Dokumentacja języka Python definiuje te wymagania dotyczące kluczowych obiektów, tzn. Muszą być możliwe do skrócenia .
źródło
hash(self.name)
wygląda ładniej niżself.name.__hash__()
, a jeśli tak, to możesz zrobić,hash((x, y))
aby uniknąć XOR.x.__hash__()
takie dzwonienie jest również nieprawidłowe , ponieważ może dawać niepoprawne wyniki: pastebin.com/C9fSH7eFand
dla__eq__
ale potem pomyślałem „dlaczego nie używając krotki?” ponieważ i tak często to robię (myślę, że jest to bardziej czytelne). Z jakiegoś dziwnego powodu moje oczy nie wróciły jednak do pytania__hash__
.__ne__()
został „naprawiony” .Alternatywą w Pythonie 2.6 lub nowszym jest użycie
collections.namedtuple()
- oszczędza ci to pisania specjalnych metod:źródło
Zastępujesz,
__hash__
jeśli chcesz specjalnej semantyki mieszania i /__cmp__
lub__eq__
aby twoja klasa była użyteczna jako klucz. Obiekty, które porównują równe, muszą mieć tę samą wartość skrótu.Python spodziewa
__hash__
się zwrócić liczbę całkowitą, zwracanieBanana()
nie jest zalecane :)Jak zauważyłeś, klasy zdefiniowane
__hash__
przez użytkownika mają domyślnie te wywołaniaid(self)
.Dokumentacja zawiera dodatkowe wskazówki :
źródło
__eq__
albo__cmp__
.__cmp__
jest ci dane przez Python, jeśli jest to klasa zdefiniowana przez użytkownika, ale prawdopodobnie i tak chcesz je zastąpić, aby uwzględnić nową semantykę.cmp
i używać=
klas użytkowników, które nie zastępują tych metod, jedną z nich należy zaimplementować, aby spełnić wymaganie pytającego, że instancje o podobnej nazwie i lokalizacji mają ten sam klucz słownika.