Python Vergleich
Aufgrund der Art und Weise, wie Proto-Daten serialisiert werden, können Sie sich nicht auf die Wire-Repräsentation einer Proto-Nachrichteninstanz verlassen, um festzustellen, ob ihr Inhalt mit dem einer anderen Instanz übereinstimmt. Eine Teilmenge der Möglichkeiten, wie eine Proto-Nachrichteninstanz im Wire-Format variieren kann, umfasst Folgendes:
- Das Protobuf-Schema ändert sich auf bestimmte Weise.
- Ein Map-Feld speichert seine Werte in einer anderen Reihenfolge.
- Das Binärformat wird mit unterschiedlichen Flags (wie opt vs. debug) erstellt.
- Die Protobuf-Bibliothek wird aktualisiert.
Aufgrund dieser Variationen, die serialisierte Daten aufweisen können, beinhaltet die Ermittlung der Gleichheit andere Methoden.
Vergleichsmethoden
Sie können Protocol Buffer-Nachrichten mit dem Standard-Python-Operator == auf Gleichheit vergleichen. Der Vergleich zweier Objekte mit dem ==-Operator vergleicht mit message.ListFields(). Beim Testen können Sie self.assertEqual(msg1, msg2) verwenden.
Zwei Nachrichten gelten als gleich, wenn sie denselben Typ und alle entsprechenden Felder gleich haben. Der Ungleichheitsoperator != ist die exakte Umkehrung von ==.
Nachrichtengleichheit ist rekursiv: Damit zwei Nachrichten gleich sind, müssen auch alle geschachtelten Nachrichten gleich sein.
Feldgleichheit und Anwesenheit
Die Gleichheitsprüfung für Felder basiert auf dem Wert. Für Felder mit expliziter Anwesenheit wird auch die Anwesenheit eines Feldes berücksichtigt.
Ein Feld, das explizit auf seinen Standardwert gesetzt ist, wird **nicht** als gleich zu einem Feld betrachtet, das nicht gesetzt ist.
Betrachten Sie beispielsweise die folgende Nachricht, die ein Feld mit expliziter Anwesenheit hat:
edition = "2023";
message MyMessage {
int32 value = 1; // 'explicit' presence by default in Editions
}
Wenn Sie zwei Instanzen erstellen, eine, bei der value nicht gesetzt ist, und eine, bei der value explizit auf 0 gesetzt ist, sind diese nicht gleich.
msg1 = MyMessage()
msg2 = MyMessage()
msg2.value = 0
assert not msg1.HasField("value")
assert msg2.HasField("value")
assert msg1 != msg2
Dasselbe Prinzip gilt für Unter-Nachrichtenfelder: Eine nicht gesetzte Unter-Nachricht ist nicht gleich einer Unter-Nachricht, die vorhanden, aber leer ist (eine Standardinstanz der Unter-Nachrichtenklasse).
Für Felder mit impliziter Anwesenheit wird das Feld immer anhand seines Wertes mit dem entsprechenden Feld in der anderen Nachricht verglichen, da die Anwesenheit nicht verfolgt werden kann.
Dieses Verhalten, bei dem die Anwesenheit Teil der Gleichheitsprüfung ist, unterscheidet sich von der Art und Weise, wie einige andere Sprachen oder Protobuf-Bibliotheken die Gleichheit handhaben könnten, bei der nicht gesetzte Felder und Felder, die auf ihren Standardwert gesetzt sind, manchmal als äquivalent behandelt werden (oft aus Kompatibilitätsgründen mit dem Wire-Format). In Python führt == eine strengere Prüfung durch.
Andere Feldtypen
- Wiederholte Felder sind gleich, wenn sie die gleiche Anzahl von Elementen haben und jedes entsprechende Element gleich ist. Die Reihenfolge der Elemente ist wichtig.
- Map-Felder sind gleich, wenn sie die gleiche Menge von Schlüssel-Wert-Paaren haben. Die Reihenfolge der Paare spielt keine Rolle.
- Gleitkommafelder (
floatunddouble) werden nach Wert verglichen. Beachten Sie die üblichen Vorbehalte bei Gleitkommavergleichen.