Was muss ich tun, um meine Objekte eines benutzerdefinierten Typs als Schlüssel in einem Python-Wörterbuch zu verwenden (wobei ich nicht möchte, dass die "Objekt-ID" als Schlüssel fungiert), z
class MyThing:
def __init__(self,name,location,length):
self.name = name
self.location = location
self.length = length
Ich möchte MyThing's als Schlüssel verwenden, die als gleich angesehen werden, wenn Name und Ort gleich sind. Von C # / Java bin ich es gewohnt, eine Methode für Gleichheit und Hashcode überschreiben und bereitstellen zu müssen, und verspreche, nichts zu mutieren, von dem der Hashcode abhängt.
Was muss ich in Python tun, um dies zu erreichen? Soll ich überhaupt?
(In einem einfachen Fall, wie hier, ist es vielleicht besser, einfach ein Tupel (Name, Ort) als Schlüssel zu platzieren - aber ich möchte, dass der Schlüssel ein Objekt ist.)
python
dictionary
Anonym
quelle
quelle
MyThing
, wenn sie dasselbe habenname
undlocation
das Wörterbuch indizieren, um denselben Wert zurückzugeben, auch wenn sie separat als zwei verschiedene "Objekte" erstellt wurden.Antworten:
Sie müssen 2 Methoden hinzufügen , beachten Sie
__hash__
und__eq__
:In der Python- Diktatdokumentation werden diese Anforderungen für Schlüsselobjekte definiert, dh sie müssen hashbar sein .
quelle
hash(self.name)
sieht besser aus alsself.name.__hash__()
, und wenn Sie dies tun und tun könnenhash((x, y))
, um XORing selbst zu vermeiden.x.__hash__()
wie das auch ist falsch , weil es kann produzieren falsche Ergebnisse: pastebin.com/C9fSH7eFand
für verwendet,__eq__
aber dann dachte ich: "Warum nicht Tupel verwenden?" weil ich das sowieso oft mache (ich denke es ist besser lesbar). Aus irgendeinem seltsamen Grund gingen meine Augen jedoch nicht zurück, um Fragen zu stellen__hash__
.__ne__()
wurde "behoben" .Eine Alternative in Python 2.6 oder höher ist die Verwendung
collections.namedtuple()
- Sie können keine speziellen Methoden schreiben:quelle
Sie überschreiben,
__hash__
wenn Sie eine spezielle Hash-Semantik wünschen und__cmp__
oder__eq__
um Ihre Klasse als Schlüssel verwendbar zu machen. Objekte, die gleich sind, müssen denselben Hashwert haben.Python erwartet
__hash__
eine Ganzzahl, eine RückgabeBanana()
wird nicht empfohlen :)Benutzerdefinierte Klassen haben
__hash__
standardmäßig Aufrufeid(self)
, wie Sie bemerkt haben.Die Dokumentation enthält einige zusätzliche Tipps :
quelle
__eq__
oder__cmp__
.__cmp__
wird Ihnen von Python gegeben, wenn es sich um eine benutzerdefinierte Klasse handelt, aber Sie möchten sie wahrscheinlich trotzdem überschreiben, um neue Semantiken zu berücksichtigen.cmp
und verwenden können,=
die diese Methoden nicht überschreiben, muss eine davon implementiert werden, um die Anforderung des Fragestellers zu erfüllen, dass Instanzen mit ähnlichem Namen und Speicherort denselben Wörterbuchschlüssel haben.