Set "in" - operator: Verwendungen der Gleichheit oder Identität?
class A(object):
def __cmp__(self):
print '__cmp__'
return object.__cmp__(self)
def __eq__(self, rhs):
print '__eq__'
return True
a1 = A()
a2 = A()
print a1 in set([a1])
print a1 in set([a2])
Warum erste Zeile druckt Wahr, aber die zweite druckt Falsch? Und weder eingibt Betreiber eq?
Ich bin mit Python 2.6
- Setzt wahrscheinlich verwenden Sie hash-codes vor der Gleichheit. Versuchen Sie, die Umsetzung
__hash__
. - haben Sie versucht, diesen code ausführen mit der
__cmp__
Funktion auskommentiert? x.__contains__(y) <==> y in x
- nur um sicherzustellen, dass Sie wissen... der Satz ist nicht erforderlich für den in-operator zu arbeiten. Wenn Sie brauchen nur einen einfachen test a1 [a1] ist in Ordnung.
- Interessant... wenn Sie dann entfernen Sie den set, erst der zweite (a1 [a2]) ruft Equalizer. Ich denke, dass der in-operator prüft Identität zunächst als Optimierung?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie definieren,
__hash__
zu. Zum BeispielFunktioniert wie erwartet.
Als eine Allgemeine Regel, jede Zeit, die Sie implementieren
__cmp__
sollten Sie implementieren eine__hash__
so dass für allex
undy
so dassx == y
,x.__hash__() == y.__hash__()
.x in my_set
) erfolgt durch den ersten Aufrufx.__hash__()
, überprüfung, ob alle Werte inmy_set
hash-Wert, dann nur aufrufen__eq__
wenn ein passendes Objekt gefunden wird.__hash__
Umsetzung einbezogen werden sollten, die die gleichen Attribute des Objekts, wie die__eq__
Umsetzung. (Nur schieben Sie Sie alle in ein Tupel undhash()
dass.)__cmp__
zu fehlen scheint dieother
aargument.Set __enthält__ lässt Prüfungen in der folgenden Reihenfolge:
Den entsprechenden C-source-code ist im Objekte/setobject.c::set_lookkey() und Objekte/Objekt.c::PyObject_RichCompareBool().
Sets und dictionaries gewinnen Ihre Geschwindigkeit, indem Sie mit hashing als eine schnelle Angleichung der vollen Gleichberechtigung überprüfen. Wenn Sie möchten, neu zu definieren, Gleichheit, benötigen Sie in der Regel zu einer Neudefinition der hash-Algorithmus, so dass es konsistent ist.
Die Standard-hash-Funktion verwendet die Identität des Objekts, die ist ziemlich nutzlos, da eine schnelle Angleichung der vollen Gleichberechtigung, aber zumindest können Sie eine beliebige Instanz der Klasse als dictionary-Schlüssel und gespeicherten Wert abrufen zu können, wenn Sie pass-genau das gleiche Objekt wie einen Schlüssel. Aber es bedeutet, dass wenn Sie neu definieren, Gleichheit und nicht neu zu definieren, hash-Funktion, Ihre Objekte werden in ein dictionary/set, ohne zu Klagen über nicht in der hashable, aber noch nicht wirklich so funktioniert, wie Sie es von Ihnen erwarten.
Sehen die offizielle python-docs auf
__hash__
für mehr details.Eine tangentiale Antwort, aber deine Frage und meine Tests machte mich neugierig. Wenn Sie ignorieren die set-Betreiber, die die Quelle Ihrer
__hash__
problem, es stellt sich heraus, Ihre Frage ist noch interessant.Danke für die Hilfe, die ich bekam auf diese Frage ALSO, ich war in der Lage zu jagen, den in-operator durch den source-code, es ist root. In der Nähe der Unterseite fand ich die PyObject_RichCompareBool Funktion, die in der Tat tests für Identität (siehe auch den Kommentar über "Schnelles Ergebnis") vor dem testen auf Gleichheit.
Also, wenn ich das missverstehen, wie die Dinge funktionieren, die technische Antwort auf Ihre Frage ist zunächst-Identität und Gleichheit durch die Gleichheit testen Sie selbst. Nur zu wiederholen, das ist nicht die Quelle des Verhaltens, die Sie waren zu sehen, sondern nur die technische Antwort auf deine Frage.
Wenn ich das falsch verstanden, die Quelle, die jemand, bitte mich gerade.
Sets scheinen hash-codes, die dann Identität, vor dem Vergleich auf Gleichheit. Die folgenden code:
Ausgänge:
Was passiert zu sein scheint:
in
- operator berechnet.