Welche Methoden müssen überschrieben / implementiert werden, wenn benutzerdefinierte Klassen in Python sortierbar und / oder hashbar gemacht werden sollen?
Worauf sollten Sie achten?
Ich tippe dir({})
in meinen Interpreter, um eine Liste der Methoden für integrierte Diktate zu erhalten. Von diesen gehe ich davon aus, dass ich eine Teilmenge von implementieren muss
['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']
Gibt es einen Unterschied, welche Methoden für Python3 im Gegensatz zu Python2 implementiert werden müssen?
__cmp__
dieser entfernt wurde.Antworten:
Ich hätte dies fast als Kommentar zu den anderen Antworten gepostet, aber es ist wirklich eine Antwort an und für sich.
Um Ihre Artikel sortierbar zu machen, müssen sie nur implementiert werden
__lt__
. Dies ist die einzige Methode, die von der eingebauten Sortierung verwendet wird.Die anderen Vergleiche oder
functools.total_ordering
werden nur benötigt, wenn Sie die Vergleichsoperatoren tatsächlich mit Ihrer Klasse verwenden möchten.Um Ihre Artikel hashbar zu machen, implementieren Sie
__hash__
wie von anderen angegeben. Sie sollten auch__eq__
auf kompatible Weise implementieren - Elemente, die gleichwertig sind, sollten denselben Hash haben.quelle
__lt__
könnte dazu führen, dass Python unvorhersehbar sortiert wird. (Zum Beispiel, wenn x .__ lt __ (y) und y .__ lt __ (x))__key__
Funktion empfehlen , die die Instanz in ein Tupel verwandelt, und dann nur__lt__
(self.__key__() < other.__key__()
) und__hash__
(hash(self.__key__())
) verwenden.Es gibt keinen Unterschied zwischen Python 2 und 3.
Zur Sortierbarkeit:
Sie sollten Vergleichsmethoden definieren. Dies macht Ihre Artikel sortierbar. Im Allgemeinen sollten Sie nicht bevorzugen
__cmp__()
.Normalerweise benutze ich den Dekorator functools.total_ordering.
Sie sollten darauf achten, dass Ihre Vergleichsmethoden keine Nebenwirkungen haben. (Ändern Sie einen der Werte des Objekts)
Zum Hashing:
Sie sollten die
__hash__()
Methode implementieren . Ich denke, der beste Weg ist die Rückkehrhash(repr(self))
, also wäre Ihr Hash einzigartig.quelle
functools.total_ordering
aus der Dokumentation finden Sie hier .Es gibt verschiedene Möglichkeiten, Ihr Objekt sortierbar zu markieren. Erster Vergleich, definiert durch eine Reihe von Funktionen:
Es ist auch möglich, nur eine Funktion zu definieren:
Und die letzte sollte definiert werden, wenn Sie eine benutzerdefinierte
__hash__
Funktion definieren möchten . Siehe das Dokument .quelle
__cmp__()
spezielle Methode nicht mehr unterstützt", siehe den entsprechenden Abschnitt hier .Die Implementierungsmethode
__lt__(self,other)
ist die Antwort, um Ihre Klasse sortierbar zu machen.Es kann nicht nur für die integrierte Methode verwendet werden
sorted(iterable)
, sondern auch für die Prioritätswarteschlange über dasheapq
Modul.Außerdem mag ich das Design von Python nicht, so dass viele
'__ge__', '__gt__', '__le__', '__lt__', '__ne__'
Methoden überhaupt nicht intuitiv sind !Im Gegensatz dazu gibt Java
Interface Comparable<T>
(siehe Java-Dokument ) eine negative Ganzzahl, eine Null oder eine positive Ganzzahl zurück, da dieses Objekt kleiner, gleich oder größer als das angegebene Objekt ist, was direkt und freundlich ist !quelle