Frage

Ich hatte einen seltsamen Fehler, wenn ein Feature den Python 3.1 Gabel meines Programms zu portieren. Ich verengte an die folgende Hypothese nach unten:

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

Ist das wahr?

Hier ist, was in Python geschieht 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 löse ich mein persönliches Problem? Ich habe ein Objekt, das eine ChangeTracker WeakKeyDictionary speichert, die auf mehrere Objekte Punkte, für jeden den Wert ihrer Beize-Dump zu einem bestimmten Zeitpunkt in der Vergangenheit geben. Jedes Mal, wenn ein vorhandenes Objekt freigegeben wird, wird die Änderung Tracker sagt, ob seine neue Beize zu seinem alten identisch ist daher zu sagen, ob das Objekt in der Zwischenzeit verändert hat. Das Problem ist, jetzt kann ich nicht einmal prüfen, ob das angegebene Objekt in der Bibliothek ist, weil es macht es eine Ausnahme über das Objekt erhöht unhashable zu sein. (Denn es hat eine __eq__ Methode.) Wie kann ich dieses Problem umgehen?

War es hilfreich?

Lösung

Ja, wenn Sie __eq__ definieren, der Standard-__hash__ (nämlich im Speicher die Adresse des Objekts Hashing) geht weg. Dies ist wichtig, weil Hashing mit Gleichheit konsistent sein muss. Gleich Objekte müssen die gleiche Hash

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

Andere Tipps

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

  

Wenn eine Klasse, die __eq__() überschreibt   muss die Umsetzung behalten   __hash__() von einer übergeordneten Klasse, der Dolmetscher muss dies gesagt werden,   explizit durch __hash__ = <ParentClass>.__hash__ Einstellung. Ansonsten der   Vererbung von __hash__() wird   blockiert, wie wenn __hash__ gewesen   explizit auf Keine.

Überprüfen Sie die Python 3 Handbuch auf object.__hash__ :

  

Wenn eine Klasse definiert keine __eq__() Methode es keine __hash__() Operation definieren sollte entweder; , wenn es __eq__() definiert, aber nicht __hash__(), seine Instanzen als Elemente in hashable Sammlungen nicht nutzbar sein werden.

Der Schwerpunkt liegt sie.

Wenn Sie faul sein wollen, es klingt wie Sie nur __hash__(self) definieren id(self) zurückzukehren:

  

Benutzerdefinierte Klassen haben __eq__() und __hash__() Methoden standardmäßig; mit ihnen, zu vergleichen, alle Objekte ungleich (außer mit sich selbst) und x.__hash__() kehrt id(x).

Ich bin kein Python-Experte, aber wäre es nicht sinnvoll, dass, wenn Sie eine eq-Methode zu definieren, können Sie auch als auch ein Hash-Verfahren definieren müssen (die den Hash-Wert für ein Objekt berechnet) Andernfalls der Hashing-Mechanismus würde nicht wissen, ob es das gleiche Objekt treffen, oder ein anderes Objekt nur mit dem gleichen Hash-Wert. Eigentlich ist es umgekehrt, es würde wahrscheinlich verschiedene Hash-Werte für Objekte als gleich von Ihrer __eq__ Methode am Ende der Berechnung.

Ich habe keine Ahnung, was die Hash-Funktion, obwohl genannt wird, __hash__ vielleicht? :)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top