Python 比较
描述 Python 如何比较对象。
由于 proto 数据的序列化方式,您不能依赖 proto 消息实例的线表示来确定其内容是否与另一个实例相同。线格式 proto 消息实例可能变化的几种方式包括以下:
- protobuf 模式以某些方式发生变化。
- map 字段以不同的顺序存储其值。
- 二进制文件使用不同的标志构建(例如优化版与调试版)。
- protobuf 库已更新。
由于序列化数据可能以这些方式变化,因此确定相等性涉及其他方法。
比较方法
您可以使用标准 Python == 运算符比较 protocol buffer 消息的相等性。使用 == 运算符比较两个对象会使用 message.ListFields() 进行比较。在测试时,您可以使用 self.assertEqual(msg1, msg2)。
如果两个消息具有相同的类型且所有对应的字段都相等,则它们被视为相等。不相等运算符 != 是 == 的精确反转。
消息相等性是递归的:要使两个消息相等,任何嵌套消息也必须相等。
字段相等性和存在性
字段的相等性检查是基于值的。对于具有显式存在的字段,字段的存在性也考虑在内。
显式设置为其默认值的字段与未设置的字段不被视为相等。
例如,考虑以下具有显式存在字段的消息
edition = "2023";
message MyMessage {
int32 value = 1; // 'explicit' presence by default in Editions
}
如果您创建两个实例,一个实例中 value 未设置,另一个实例中 value 显式设置为 0,则它们将不相等
msg1 = MyMessage()
msg2 = MyMessage()
msg2.value = 0
assert not msg1.HasField("value")
assert msg2.HasField("value")
assert msg1 != msg2
同样的原则也适用于子消息字段:未设置的子消息不等于存在但为空的子消息(子消息类的默认实例)。
对于具有隐式存在的字段,由于无法跟踪存在性,因此该字段始终通过其值与另一个消息中的相应字段进行比较。
这种行为,即存在性是相等性检查的一部分,与某些其他语言或 protobuf 库处理相等性的方式不同,在这些语言或库中,未设置的字段和设置为其默认值的字段有时被视为等效(通常是为了线格式兼容性)。在 Python 中,== 执行更严格的检查。
其他字段类型
- 如果重复字段具有相同数量的元素且每个相应元素相等,则它们相等。元素的顺序很重要。
- 如果映射字段具有相同的键值对集合,则它们相等。键值对的顺序无关紧要。
- 浮点字段(
float和double)按值比较。请注意浮点比较的常见注意事项。