Sie sollten die Methode implementieren __eq__
:
class MyClass:
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
def __eq__(self, other):
if not isinstance(other, MyClass):
# don't attempt to compare against unrelated types
return NotImplemented
return self.foo == other.foo and self.bar == other.bar
Jetzt gibt es aus:
>>> x == y
True
Beachten Sie, dass durch die Implementierung __eq__
Instanzen Ihrer Klasse automatisch nicht mehr verwertbar sind. Dies bedeutet, dass sie nicht in Mengen und Diktaten gespeichert werden können. Wenn Sie keinen unveränderlichen Typ modellieren (dh wenn die Attribute foo
undbar
Wert innerhalb der Lebensdauer Ihres Objekts ändern), wird empfohlen, Ihre Instanzen einfach als nicht verwertbar zu belassen.
Wenn Sie einen unveränderlichen Typ modellieren, sollten Sie auch den Datenmodell-Hook implementieren __hash__
:
class MyClass:
...
def __hash__(self):
# necessary for instances to behave sanely in dicts and sets.
return hash((self.foo, self.bar))
Eine allgemeine Lösung, wie die Idee __dict__
, Werte zu durchlaufen und zu vergleichen, ist nicht ratsam - sie kann niemals wirklich allgemein sein, weil die__dict__
möglicherweise unvergleichliche oder nicht verwischbare Typen enthält.
NB: Beachten Sie, dass Sie vor Python 3 möglicherweise __cmp__
anstelle von verwenden müssen __eq__
. Python 2-Benutzer möchten möglicherweise auch implementieren __ne__
, da ein sinnvolles Standardverhalten für Ungleichheit (dh das Invertieren des Gleichheitsergebnisses) in Python 2 nicht automatisch erstellt wird.
return NotImplemented
(anstatt zu erhöhenNotImplementedError
). Dieses Thema wird hier behandelt: stackoverflow.com/questions/878943/…Sie überschreiben die umfangreichen Vergleichsoperatoren in Ihrem Objekt.
So was:
quelle
__eq__()
, aber nur einer von__lt__()
,__le__()
,__gt__()
, oder__ge__()
ist zusätzlich zu dem Bedarf. Daraus kann Python die anderen Methoden ableiten. Siehefunctools
für weitere Informationen.functools
Modul, funktioniert jedoch nicht für Standardkomparatoren: FunktioniertMyObj1 != Myobj2
nur, wenn die__ne__()
Methode implementiert ist.@functools.total_ordering
Dekorator für Ihre Klasse zu verwenden. Dann können Sie wie oben nur einen__eq__
und einen anderen definieren, und der Rest wird abgeleitetImplementieren Sie die
__eq__
Methode in Ihrer Klasse. etwas wie das:Bearbeiten: Wenn Sie möchten, dass Ihre Objekte genau dann gleich verglichen werden, wenn sie gleiche Instanzwörterbücher haben:
quelle
self is other
sehen, ob es sich um dasselbe Objekt handelt.AttributeError
. Sie müssen die Zeile einfügenif hasattr(other, "path") and hasattr(other, "title"):
(wie dieses schöne Beispiel in der Python-Dokumentation).Zusammenfassend:
__eq__
sei denn__cmp__
, Sie führen Python <= 2.0 aus (__eq__
wurde in 2.1 hinzugefügt).__ne__
(sollte so etwas wiereturn not self.__eq__(other)
oderreturn not self == other
außer einem ganz besonderen Fall sein)Wenn Sie mit einem Objekt vergleichen möchten, das None sein kann, müssen Sie es implementieren. Der Dolmetscher kann es nicht erraten ... (siehe Beispiel unten)
quelle
Abhängig von Ihrem speziellen Fall können Sie Folgendes tun:
Siehe Python-Wörterbuch aus den Feldern eines Objekts
quelle
Mit Datenklassen in Python 3.7 (und höher) ist ein Vergleich von Objektinstanzen auf Gleichheit eine integrierte Funktion.
Für Python 3.6 ist ein Backport für Datenklassen verfügbar.
quelle
Beim Vergleichen von Objektinstanzen wird die
__cmp__
Funktion aufgerufen.Wenn der Operator == standardmäßig nicht für Sie
__cmp__
funktioniert , können Sie die Funktion für das Objekt jederzeit neu definieren .Bearbeiten:
Wie bereits erwähnt, ist die
__cmp__
Funktion seit 3.0 veraltet. Stattdessen sollten Sie die Methoden "Rich Compare" verwenden.quelle
Ich habe das geschrieben und in ein
test/utils
Modul in meinem Projekt eingefügt. In Fällen, in denen es sich nicht um eine Klasse handelt, planen Sie einfach das alte Diktat. Dadurch werden beide Objekte durchlaufen und sichergestelltEs ist groß ... es ist nicht sexy ... aber oh Boi, es funktioniert!
Sie können es ein wenig aufräumen, indem Sie das entfernen
_assert
und einfach nur ol 'verwenden,assert
aber dann ist die Meldung, die Sie erhalten, wenn es fehlschlägt, sehr wenig hilfreich.quelle
Sie sollten die Methode implementieren
__eq__
:quelle
Das Folgende funktioniert (in meinen begrenzten Tests) durch einen tiefen Vergleich zwischen zwei Objekthierarchien. In behandelt verschiedene Fälle, einschließlich der Fälle, in denen Objekte selbst oder ihre Attribute Wörterbücher sind.
Dies ist ein sehr kniffliger Code. Fügen Sie daher in Kommentaren Fälle hinzu, die für Sie möglicherweise nicht funktionieren.
quelle
quelle
Wenn Sie es mit einer oder mehreren Klassen zu tun haben, die Sie von innen nicht ändern können , gibt es allgemeine und einfache Möglichkeiten, die auch nicht von einer diff-spezifischen Bibliothek abhängen:
Einfachste, für sehr komplexe Objekte unsichere Methode
pickle
ist eine sehr verbreitete Serialisierungsbibliothek für Python-Objekte und kann daher so ziemlich alles serialisieren. Im obigen Snippet vergleiche ich dasstr
von serialisierta
mit dem vonb
. Im Gegensatz zur nächsten Methode hat diese den Vorteil, dass auch benutzerdefinierte Klassen auf Typprüfung überprüft werden können.Der größte Aufwand: Aufgrund spezifischer Ordnungs- und [de / en] -Codierungsmethoden wird
pickle
möglicherweise nicht das gleiche Ergebnis für gleiche Objekte erzielt , insbesondere bei komplexeren Objekten (z. B. Listen verschachtelter Instanzen benutzerdefinierter Klassen), wie Sie sie häufig finden in einigen Bibliotheken von Drittanbietern. Für diese Fälle würde ich einen anderen Ansatz empfehlen:Gründliche, für jedes Objekt sichere Methode
Sie können eine rekursive Reflexion schreiben, die Ihnen serialisierbare Objekte liefert, und dann die Ergebnisse vergleichen
Jetzt spielt es keine Rolle, was Ihre Objekte sind, tiefe Gleichheit ist sicher zu funktionieren
Die Anzahl der Vergleiche spielt ebenfalls keine Rolle
Mein Anwendungsfall hierfür war die Überprüfung der tiefen Gleichheit zwischen einer Vielzahl bereits trainierter Modelle für maschinelles Lernen in BDD-Tests. Die Modelle gehörten zu einer Vielzahl von Bibliotheken von Drittanbietern.
__eq__
Wie andere Antworten hier zu implementieren , war für mich sicherlich keine Option.Bedeckt alle Basen
Möglicherweise befinden Sie sich in einem Szenario, in dem eine oder mehrere der verglichenen benutzerdefinierten Klassen keine
__dict__
Implementierung haben . Das ist keineswegs üblich, aber es handelt sich um einen Subtyp innerhalb des Random Forest-Klassifikators von sklearn :<type 'sklearn.tree._tree.Tree'>
. Behandeln Sie diese Situationen in einem Einzelfall - zum Beispiel speziell , ich den Inhalt des betroffenen Typs mit dem Inhalt einer Methode zu ersetzen , entschieden , die mir repräsentative Informationen über die Instanz (in diesem Fall das gibt__getstate__
Methode). Für eine solche, in der zweiten bis letzten Zeilebase_typed
wurdeBearbeiten: Aus Gründen der Organisation habe ich die letzten beiden Zeilen
base_typed
durch ersetztreturn dict_from(obj)
und eine wirklich allgemeine Reflexion implementiert, um dunkelere Bibliotheken aufzunehmen (ich sehe dich an, Doc2Vec).Beachten Sie, dass keine der oben genannten Methoden
True
für verschiedene Objekte mit denselben Schlüssel-Wert-Paaren, aber unterschiedlichen Schlüssel / Wert-Reihenfolgen wie in ergibtWenn Sie dies jedoch möchten, können Sie die integrierte
sorted
Methode von Python ohnehin vorher verwenden.quelle
Wenn Sie einen Attribut-für-Attribut-Vergleich durchführen möchten und feststellen möchten, ob und wo dies fehlschlägt, können Sie das folgende Listenverständnis verwenden:
Der zusätzliche Vorteil hierbei ist, dass Sie beim Debuggen in PyCharm eine Zeile zusammendrücken und in das Fenster "Ausdruck auswerten" eingeben können.
quelle
Ich habe das erste Beispiel ausprobiert (siehe 7 oben) und es hat in ipython nicht funktioniert. Beachten Sie, dass cmp (obj1, obj2) eine "1" zurückgibt, wenn es mit zwei identischen Objektinstanzen implementiert wird. Seltsamerweise gibt das Objekt weiterhin eine "1" zurück, wenn ich einen der Attributwerte ändere und mit cmp (obj1, obj2) neu vergleiche. (Seufzer...)
Ok, Sie müssen also zwei Objekte iterieren und jedes Attribut mit dem Zeichen == vergleichen.
quelle
Die Instanz einer Klasse im Vergleich zu == ist ungleich. Der beste Weg ist, den cmp zu ass Funktion Ihrer Klasse , die das Zeug .
Wenn Sie den Inhalt vergleichen möchten, können Sie einfach cmp (obj1, obj2) verwenden.
In Ihrem Fall cmp (doc1, doc2) Es wird -1 zurückgegeben, wenn der Inhalt identisch ist.
quelle