Pickle序列化含自定义对象字典后反序列化结果不一致问题
问题原因分析
你遇到的问题根源在于自定义类实例的默认比较逻辑:Python中,自定义类的实例默认是通过**内存地址(身份)**来判断相等性的,也就是is运算符的判断逻辑。反序列化时,pickle会创建一个全新的对象实例,它的内存地址和原对象肯定不一样,所以即使两个实例的属性完全相同,==比较也会返回False,进而导致包含它们的字典比较结果为False。
解决方案:实现自定义的相等性判断
要让序列化前后的字典比较返回True,我们需要给ExampleClass添加__eq__方法,定义两个实例在什么情况下被视为相等(也就是所有属性值完全匹配)。同时,为了遵循Python的最佳实践,建议同时实现__hash__方法(这样实例可以被安全地用作字典键或放入集合中,保证哈希逻辑和相等逻辑的一致性)。
修改后的代码如下:
import pickle class ExampleClass(object): def __init__(self, obj_id, name, type): self.obj_id = obj_id self.name = name self.type = type def __eq__(self, other): # 先判断对方是否为同一类的实例 if not isinstance(other, ExampleClass): return False # 比较所有属性的值,全部匹配则视为相等 return (self.obj_id == other.obj_id and self.name == other.name and self.type == other.type) def __hash__(self): # 基于实例的属性生成哈希值,和__eq__逻辑保持一致 return hash((self.obj_id, self.name, self.type)) my_obj = ExampleClass(1, 'tu42', 'bas5') example_dict = {'object': my_obj, 'date': '02041980', 'event': 'test'} with open("test.pickle", "wb") as handle: pickle.dump(example_dict, handle, protocol=pickle.HIGHEST_PROTOCOL) with open("test.pickle", "rb") as handle: reconstituted = pickle.load(handle) print(example_dict) print(reconstituted) print(example_dict == reconstituted) # 现在会输出True print(my_obj is reconstituted['object']) # 输出False,因为是不同实例,但逻辑相等
运行结果说明
修改后,example_dict == reconstituted会返回True,因为字典会递归比较每个键对应的值:
- 字符串类型的
date和event本身就按值比较,结果相等; - 自定义类的实例现在会用我们实现的
__eq__方法比较,属性全部匹配就返回True。
而my_obj is reconstituted['object']仍然返回False,这是正常的——反序列化确实创建了新的对象实例,但它们的逻辑状态完全一致,这正是序列化想要达到的效果。
内容的提问来源于stack exchange,提问作者Yannis
相关产品推荐
相关产品推荐

