Python の比較

Pythonがオブジェクトを比較する方法について説明します。

protoデータのシリアル化方法のため、protoメッセージインスタンスのワイヤー表現が別のインスタンスと同じコンテンツであるかどうかを判断するために、それに頼ることはできません。ワイヤーフォーマットのprotoメッセージインスタンスが異なる可能性のある方法の一部には、以下が含まれます。

  • protobufスキーマが特定の方法で変更される。
  • マップフィールドがその値を異なる順序で格納する。
  • バイナリが異なるフラグ(optとdebugなど)でビルドされる。
  • protobufライブラリが更新される。

シリアル化されたデータが異なる可能性のあるこれらの方法のため、等価性を判断するには他のメソッドが必要になります。

比較メソッド

Protocol Bufferメッセージの等価性は、標準のPython ==演算子を使用して比較できます。==演算子を使用して2つのオブジェクトを比較すると、message.ListFields()と比較されます。テストでは、self.assertEqual(msg1, msg2)を使用できます。

2つのメッセージは、同じ型を持ち、対応するすべてのフィールドが等しい場合に等しいと見なされます。不等号演算子!===の厳密な逆です。

メッセージの等価性は再帰的です。2つのメッセージが等しいためには、ネストされたメッセージもすべて等しくなければなりません。

フィールドの等価性と存在

フィールドの等価性チェックは値に基づいています。明示的な存在を持つフィールドの場合、フィールドの存在も考慮されます。

デフォルト値に明示的に設定されたフィールドは、設定されていないフィールドと等しいとは見なされません

例えば、明示的な存在フィールドを持つ以下のメッセージを考えてみましょう。

edition = "2023";
message MyMessage {
  int32 value = 1; // 'explicit' presence by default in Editions
}

valueが設定されていないインスタンスと、valueが明示的に0に設定されているインスタンスの2つを作成した場合、それらは等しくありません。

msg1 = MyMessage()
msg2 = MyMessage()
msg2.value = 0

assert not msg1.HasField("value")
assert msg2.HasField("value")
assert msg1 != msg2

この原則はサブメッセージフィールドにも適用されます。設定されていないサブメッセージは、存在するが空のサブメッセージ(サブメッセージクラスのデフォルトインスタンス)とは等しくありません。

暗黙的な存在を持つフィールドの場合、存在を追跡できないため、そのフィールドは常に、他のメッセージの対応するフィールドに対してその値で比較されます。

存在が等価性チェックの一部であるこの動作は、他の言語やprotobufライブラリが等価性を処理する方法とは異なります。それらの場合、設定されていないフィールドとデフォルト値に設定されたフィールドが同等に扱われることがあります(多くの場合、ワイヤーフォーマットの互換性のために)。Pythonでは、==はより厳密なチェックを実行します。

その他のフィールドタイプ

  • 繰り返しフィールドは、要素の数が同じで、対応する各要素が等しい場合に等しいと見なされます。要素の順序は重要です。
  • マップフィールドは、同じキーと値のペアのセットを持つ場合に等しいと見なされます。ペアの順序は重要ではありません。
  • 浮動小数点フィールドfloatdouble)は値で比較されます。浮動小数点比較に関する通常の注意事項に注意してください。