You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重写__hash__方法后pickle/dill加载对象触发AttributeError求助

解决Pickle加载含自定义类型键的字典时的AttributeError问题

问题根源

使用Pickle加载包含A类对象作为键的字典时触发AttributeError: 'A' object has no attribute 'name',核心原因是Pickle的反序列化顺序:它会先创建A类的空实例(不调用__init__),随后尝试恢复字典结构。而字典恢复时需要先对键(A对象)计算哈希值,此时A对象的name属性还未初始化,导致__hash__方法调用失败。

解决方案

方案1:通过__getstate__和__setstate__控制反序列化顺序

给A类添加这两个方法,强制优先恢复name属性,再处理字典,确保哈希计算时name已存在。

修改后的A类代码:

import pickle

class A:
    def __init__(self, name):
        self.name = name
        self.dic = dict()   # 存储以A对象为键的字典

    def __repr__(self): 
        return self.name

    def __hash__(self): 
        return hash(self.name)
    
    def __getstate__(self):
        # 按name优先的顺序返回需要序列化的属性
        return (self.name, self.dic)
    
    def __setstate__(self, state):
        # 先恢复name,再恢复字典
        self.name = state[0]
        self.dic = state[1]

B类代码保持不变,重新保存并加载即可正常运行。

方案2:给__hash__方法添加容错处理

如果不想修改序列化逻辑,可以调整__hash__方法,当name未初始化时临时用对象ID替代哈希值,保证反序列化流程能完成:

class A:
    def __init__(self, name):
        self.name = name
        self.dic = dict()

    def __repr__(self): 
        return self.name

    def __hash__(self): 
        # 当name未初始化时,用对象ID临时生成哈希
        return hash(getattr(self, 'name', id(self)))

这种方法更简洁,临时哈希仅在反序列化过程中生效,对象完全恢复后,name属性正常,哈希值也会回到预期状态,不影响后续字典操作。

关于之前__getstate__/__setstate__无效的说明

如果之前尝试过这两个方法但失败,大概率是没有保证name的恢复优先级高于字典。若在__setstate__中先恢复dic再恢复name,依然会触发相同错误,必须确保name先完成初始化。

内容的提问来源于stack exchange,提问作者simone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 08:45:46