Typen, die `__eq__` definieren, sind unerschütterlich?

Ich hatte einen seltsamen Fehler, wenn ich ein Feature auf die Python 3.1 Gabel meines Programms portierte. Ich verkleinerte es auf die folgende Hypothese:

Im Gegensatz zu Python 2.x, in Python 3.x, wenn ein Objekt eine .__eq__ Methode hat, ist es automatisch unschuldbar.

Ist das wahr?

Hier ist was passiert in Python 3.1:

 >>> class O(object): def __eq__(self, other): return 'whatever' >>> o = O() >>> d = {o: 0} Traceback (most recent call last): File "<pyshell#16>", line 1, in <module> d = {o: 0} TypeError: unhashable type: 'O' 

Die Folgefrage ist, wie kann ich mein persönliches Problem lösen? Ich habe ein Objekt ChangeTracker das ein WeakKeyDictionary speichert, das auf mehrere Objekte verweist und für jeden den Wert ihres Pickle Dump zu einem bestimmten Zeitpunkt in der Vergangenheit gibt. Immer wenn ein bestehendes Objekt eingecheckt wird, sagt der Änderungsverfolger, ob sein neuer Gurke identisch mit seinem alten ist und daher sagt, ob sich das Objekt in der Zwischenzeit geändert hat. Problem ist, jetzt kann ich nicht einmal überprüfen, ob das gegebene Objekt in der Bibliothek ist, denn es macht es eine Ausnahme über das Objekt, das unerschütterlich ist. (Ursache, dass es eine __eq__ Methode hat.) Wie kann ich das __eq__ ?

4 Solutions collect form web for “Typen, die `__eq__` definieren, sind unerschütterlich?”

Ja, wenn du __eq__ definierst, geht die Voreinstellung __hash__ (nämlich Hashing der Adresse des Objekts im Speicher) weg. Das ist wichtig, weil Hashing mit Gleichheit übereinstimmen muss: gleiche Gegenstände müssen das gleiche haben.

Die Lösung ist einfach: einfach definieren __hash__ zusammen mit der Definition __eq__ .

Dieser Absatz von http://docs.python.org/3.1/reference/datamodel.html#object. Hash

Wenn eine Klasse, die __eq__() überschreibt, die Implementierung von __hash__() aus einer übergeordneten Klasse beibehalten muss, muss der Interpreter dies explizit mit der Einstellung __hash__ = <ParentClass>.__hash__ . Andernfalls wird die Vererbung von __hash__() gesperrt, so wie __hash__ explizit auf Keine gesetzt wurde.

Überprüfe das Python 3 Handbuch auf object.__hash__ :

Wenn eine Klasse keine __eq__() Methode definiert, sollte sie auch keine __hash__() Operation definieren. Wenn es __eq__() aber nicht __hash__() , werden seine Instanzen nicht als Items in Hash-Sammlungen verwendbar.

Der Schwerpunkt liegt auf mir.

Wenn du faul sein willst, klingt es so, als __hash__(self) du einfach __hash__(self) , um id(self) :

Benutzerdefinierte Klassen haben __eq__() und __hash__() Methoden. Mit ihnen, alle Objekte vergleichen ungleich (außer mit sich) und x.__hash__() gibt id(x) .

Ich bin kein Python-Experte, aber es ist nicht sinnvoll, dass Sie bei der Definition einer eq-Methode auch eine Hash-Methode definieren müssen (die den Hash-Wert für ein Objekt berechnet). Andernfalls ist der Hash-Mechanismus Würde nicht wissen, ob es das gleiche Objekt oder ein anderes Objekt mit genau dem gleichen Hash-Wert trifft. Tatsächlich ist es umgekehrt, es würde wahrscheinlich am Ende die Berechnung von verschiedenen Hash-Werte für Objekte, die von deiner __eq__ Methode gleich sind.

Ich habe keine Ahnung, was diese Hash-Funktion genannt wird, __hash__ vielleicht? 🙂

  • Erläuterung zur Erläuterung von Hash-Objekten
  • Kurzer Python-alphanumerischer Hash mit minimalen Kollisionen
  • Python frozenset Hash-Algorithmus / Umsetzung
  • Md5 zu ganzzahligen bits in python
  • Mit pickle.dumps zu Hash-mutable Objekte
  • Warum sind keine Python-Sets hashable?
  • Hashing Tupel in Python verursacht unterschiedliche Ergebnisse in verschiedenen Systemen
  • Hash-Funktion in Python 3.3 gibt verschiedene Ergebnisse zwischen den Sessions zurück
  • Python unhash Wert
  • Der effektivste Weg, um eine Zeichenfolge einer Zeichenfolge zuzuordnen?
  • Wie kann man __hash__ definieren, wenn ein Objekt gleich einer anderen Art von Objekten sein kann?
  • Python ist die beste Programmiersprache der Welt.