重写__hash__方法后无法反序列化pickle对象问题求助
问题分析
反序列化Conflicts对象时触发Link类的__hash__方法报错,核心原因是pickle反序列化的执行顺序导致Link的属性未完全初始化时,就被要求计算哈希值。具体来说:
- 当反序列化Conflicts对象时,其关联的Link对象可能先被父类或内部结构(如集合)引用,触发
__hash__调用,但此时node_a_id/node_b_id还未通过__setstate__完成赋值。 - Network对象中的Link未触发这种提前哈希的场景,因此序列化正常。
解决方案(不修改Link的__hash__方法)
方案1:给Link类的ID属性设置默认值
在Link类定义时,为node_a_id和node_b_id设置空字符串默认值,确保即使提前触发__hash__,也不会因属性不存在报错,后续__setstate__会覆盖默认值:
class Link: node_a: ValueNode = None node_a_id : str = "" node_b: ValueNode = None node_b_id : str = "" # 原__init__、__getstate__、__setstate__、__hash__代码保持不变
方案2:控制Conflicts类的反序列化顺序
通过实现Conflicts类的__getstate__和__setstate__,强制先完成Link对象的属性恢复,再处理其他可能触发哈希的结构:
class Conflict: # 原__init__代码保持不变 def __getstate__(self): state = self.__dict__.copy() # 单独保存Link的状态,用于后续优先恢复 state["link_state"] = self.link.__getstate__() return state def __setstate__(self, state): # 优先恢复Link的属性 link_state = state.pop("link_state") self.link.__setstate__(link_state) # 再恢复Conflict自身的其他属性 self.__dict__.update(state) # 若父类需要处理状态,最后调用父类的__setstate__ # super().__setstate__(state)
内容的提问来源于stack exchange,提问作者Dayiz
相关产品推荐
相关产品推荐

