Ich bin heute auf dieses interessante Beispiel gestoßen.
%Vor% %Vor% So scheint es, dass Vergleiche in Containern in Python anders funktionieren. Ich würde erwarten, dass der Aufruf von ==
die Implementierung jedes Objekts von __eq__
verwenden würde, sonst was ist der Punkt? Zusätzlich
Bedeutet dies, dass Python is
stattdessen in Container-Implementierungen von __eq__
verwendet? Gibt es einen Weg dazu?
Mein Anwendungsfall ist, dass ich eine Datenstruktur erstelle, die von einigen der collections
ABCs erbt, und ich möchte Tests schreiben, um sicherzustellen, dass sich meine Struktur korrekt verhält. Ich dachte mir, es wäre einfach, einen Wert zu injizieren, der beim Vergleichen aufgezeichnet wurde, aber zu meiner Überraschung schlug der Test fehl, als ich sicherstellte, dass der Vergleich stattfand.
EDIT: Ich sollte erwähnen, dass dies auf Python 2.7 ist, aber ich sehe das gleiche Verhalten auf 3.3.
Die zugrunde liegende CPython-Implementierung überspringt die Gleichheitsprüfung ( ==
) für Elemente in einer Liste, wenn Elemente identisch sind ( is
).
CPython verwendet dies als eine Optimierung unter der Annahme, dass Identität Gleichheit bedeutet.
Dies ist in PyObject_RichCompareBool dokumentiert, das zum Vergleichen von Elementen verwendet wird:
Hinweis: Wenn o1 und o2 dasselbe Objekt sind, gibt PyObject_RichCompareBool () immer 1 für Py_EQ und 0 für Py_NE zurück.
Aus der Implementierung listobject.c :
%Vor% Wie Sie sehen können, solange RichCompareBool
ist 1
( True
) werden die Elemente nicht überprüft.
Und von der object.c Implementierung von PyObject_RichCompareBool
:
Um dies zu umgehen, müssen Sie die Elemente manuell vergleichen.
Python testet die Gleichheit von Sequenzen wie folgt:
%Vor%Sie können sehen, dass die Gleichheit der Elemente an jeder Position getestet wird nur , wenn die zwei Sequenzen die gleiche Länge haben, aber die Elemente an jeder Position nicht identisch sind. Wenn Sie die Verwendung von Gleichheitsprüfungen erzwingen möchten, benötigen Sie z. B.:
%Vor% Wenn x is y
, gibt es keinen Grund, x == y
aufzurufen, nach Vertrag von ==
. Python nimmt diese Abkürzung.
Dies kann verifiziert / widerlegt werden, indem in den Tests ein eq1
und ein eq2
erstellt und anschließend [eq1] == [eq2]
verwendet wird.
Wenn die Elemente is
sind, ist kein ==
beteiligt.
Der Unterschied zu den Wörterbüchern kann ähnlich erklärt werden.
Beim Vergleich zweier Listen schließt die cPython-Implementierung Mitgliedervergleiche mithilfe der Objektgleichheit ( obj1 is obj2
) kurz, da nach ein Kommentar im Code :
Wenn die zwei Objekte nicht genau das gleiche Objekt sind, dann führt cPython einen reichen Vergleich durch, indem% code_% verwendet wird, falls implementiert.
Tags und Links python python-2.7