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

带类型注解且默认值为None的数据类哈希值为何每次运行不一致?

问题解析

这个现象的核心原因在于Python 3.9/3.10版本中,dataclass在处理「带类型注解且默认值为None的字段」时,生成的__hash__方法存在异常,导致哈希值基于实例的内存地址(id)而非字段值。

具体分析三个类的行为:

  • Foo类:x和y均无类型注解,属于类属性而非dataclass实例字段。由于没有实例字段,dataclass不会生成自定义__hash__,继承自object的__hash__(基于实例id)。你设置了PYTHONHASHSEED=0,且每次运行时Foo()是第一个创建的对象,内存地址固定,因此哈希值稳定。
  • Bar类:x有类型注解且默认值为1,是dataclass实例字段;y无类型注解,为类属性。frozen=True让dataclass生成基于字段值的__hash__方法,哈希值由x=1的元组哈希决定(hash((1,))),因此每次运行稳定。
  • Foobar类:y有类型注解且默认值为None,是dataclass实例字段;x无类型注解,为类属性。本应生成基于y=None的元组哈希(hash((None,))),但Python 3.9/3.10的dataclass在此场景下未正确生成自定义__hash__,而是继承了object的__hash__。实例id每次运行时会变化(即使PYTHONHASHSEED=0,内存地址分配不固定),因此哈希值每次运行不同。

验证与修复

你可以手动为Foobar添加自定义__hash__方法来验证:

@dataclass(frozen=True)
class Foobar:
    x = 1
    y: Optional[int] = None
    
    def __hash__(self):
        return hash((self.y,))

此时运行脚本,Foobar()的哈希值会固定为hash((None,))的结果,不再随运行变化。

这个问题在Python 3.11及以上版本中已被修复,升级到更高版本即可解决该异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:55:19