相同参数下创建dataclass多个独立实例的问题咨询
行为原因
普通自定义类如果没有显式实现__eq__和__hash__方法,默认会基于实例的内存地址做相等判断和哈希值计算:哪怕两个实例的所有属性取值完全一致,只要是不同内存地址的对象,就会被判定为不相等,哈希值也不同,所以10个RegularVariable(1)放到set里长度为10。
dataclass默认会根据类中定义的所有字段自动生成__eq__和__hash__方法(frozen=True的场景下会默认启用哈希生成),这两个方法的逻辑完全基于字段取值:只要所有字段的取值相同,就会判定两个实例相等,哈希值也完全一致,所以10个DataClassVariable(1)会被set判定为同一个元素,最终长度为1。
解决方案
如果需要属性相同的实例也被判定为不同对象,可选两种实现方式:
- 方案1:关闭dataclass自动生成相等判断方法的逻辑,沿用Python默认的内存地址判断规则,只需要在装饰器中加
eq=False参数即可:
@dataclass(frozen=True, eq=False) class DataClassVariable: num_states: int
该方案的注意点:后续如果需要判断两个实例的属性是否相等,不能直接用==运算符,需要手动比对字段取值。
- 方案2:新增唯一标识字段区分不同实例,适合需要保留字段相等判断能力的场景:
from dataclasses import dataclass, field import itertools @dataclass(frozen=True) class DataClassVariable: num_states: int # 自动生成唯一自增id,不会出现在初始化参数中 _unique_id: int = field( default_factory=itertools.count().__next__, repr=False, # 不在打印结果里展示该字段,和原输出格式保持一致 # 如果需要字段相同的实例仍被==判定为相等,就加compare=False,否则删掉即可 )
该方案可以根据需求灵活控制相等判断的逻辑,不会影响原有属性的比对能力。
内容的提问来源于stack exchange,提问作者njk23
相关产品推荐
相关产品推荐

