为何成员变量值不同的Dataclass对象判定相等?
问题:Dataclass对象比较结果不符合预期
定义了包含3个成员变量的Dataclass类DiagCodes,创建两个成员变量值不同的对象并判断相等时,结果始终为True。代码如下:
from dataclasses import dataclass from typing import Optional @dataclass(init=False) class DiagCodes: __slots__ = ["indx_nbr", "diag_cd", "diag_typ_cd"] def __init__( self, indx_nbr: Optional[int] = None, diag_cd: Optional[str] = None, diag_typ_cd: Optional[str] = None, ) -> None: self.indx_nbr = indx_nbr self.diag_cd = diag_cd self.diag_typ_cd = diag_typ_cd if __name__ == "__main__": dc = DiagCodes(1) dc_empty = DiagCodes() print(dc == dc_empty) # 输出: True
按照Dataclass的默认__eq__方法实现,结果应该为False才对,使用Python版本为3.8.10。
原因与解决方案
原因
@dataclass装饰器默认会根据类体中带有类型注解的成员变量生成__eq__方法,以此作为对象相等性判断的依据。你的代码存在两个关键问题:
- 仅通过
__slots__声明成员变量,未在类体中显式定义带类型注解的字段; - 使用
init=False并手动实现__init__,但dataclass无法从__init__参数中自动识别需要纳入比较的字段。
由于dataclass检测不到任何需要比较的字段,生成的__eq__方法会将所有实例视为相等——因为没有字段可以用来区分它们。
解决方案
方式一:在类体中显式定义带类型注解的字段
保留__slots__和手动__init__,在类体中添加字段的类型注解,让dataclass识别需要比较的字段:
from dataclasses import dataclass from typing import Optional @dataclass(init=False) class DiagCodes: __slots__ = ["indx_nbr", "diag_cd", "diag_typ_cd"] # 显式定义字段类型注解 indx_nbr: Optional[int] diag_cd: Optional[str] diag_typ_cd: Optional[str] def __init__( self, indx_nbr: Optional[int] = None, diag_cd: Optional[str] = None, diag_typ_cd: Optional[str] = None, ) -> None: self.indx_nbr = indx_nbr self.diag_cd = diag_cd self.diag_typ_cd = diag_typ_cd if __name__ == "__main__": dc = DiagCodes(1) dc_empty = DiagCodes() print(dc == dc_empty) # 输出: False
方式二:手动实现__eq__方法
如果不想依赖dataclass自动生成的__eq__,可以自行实现相等性判断逻辑:
from dataclasses import dataclass from typing import Optional @dataclass(init=False) class DiagCodes: __slots__ = ["indx_nbr", "diag_cd", "diag_typ_cd"] def __init__( self, indx_nbr: Optional[int] = None, diag_cd: Optional[str] = None, diag_typ_cd: Optional[str] = None, ) -> None: self.indx_nbr = indx_nbr self.diag_cd = diag_cd self.diag_typ_cd = diag_typ_cd def __eq__(self, other): if not isinstance(other, DiagCodes): return NotImplemented return (self.indx_nbr == other.indx_nbr and self.diag_cd == other.diag_cd and self.diag_typ_cd == other.diag_typ_cd) if __name__ == "__main__": dc = DiagCodes(1) dc_empty = DiagCodes() print(dc == dc_empty) # 输出: False
内容的提问来源于stack exchange,提问作者Vandit Goel
相关产品推荐
相关产品推荐

