如何移除包含列表字段的dataclass对象列表中的重复元素
问题根因
frozen=True仅限制你不能重新给dataclass的字段赋值,不会改变字段本身的类型特性,list属于可变不可哈希类型,因此dataclass自动生成的__hash__方法无法正常工作,导致用set、dict.fromkeys等依赖哈希的方法去重时报错。
可选解决方案
方案1:替换为不可变序列类型(优先推荐)
如果业务场景不需要修改该字段的内容,直接把字段类型从List[str]替换为Tuple[str, ...]即可,无需额外自定义逻辑,直接复用dataclass自动生成的哈希和相等判断逻辑。
示例代码:
from dataclasses import dataclass from typing import Tuple @dataclass(eq=True, frozen=True) class TestClass: field1: str field_list: Tuple[str, ...] # 改为Tuple类型 # 构造对象&去重示例 obj1 = TestClass("test", ("a", "b")) obj2 = TestClass("test", ("a", "b")) obj3 = TestClass("test2", ("c", "d")) unique_objs = list(set([obj1, obj2, obj3])) # 运行正常
方案2:自定义__hash__方法
如果必须保留List类型字段,自行实现哈希方法,计算哈希时将列表转为可哈希的元组即可:
from dataclasses import dataclass from typing import List @dataclass(eq=True, frozen=True) class TestClass: field1: str field_list: List[str] def __hash__(self) -> int: # 将list转为tuple参与哈希计算 return hash((self.field1, tuple(self.field_list))) # 去重逻辑正常运行 obj1 = TestClass("test", ["a", "b"]) obj2 = TestClass("test", ["a", "b"]) obj3 = TestClass("test2", ["c", "d"]) unique_objs = list(set([obj1, obj2, obj3]))
注意:该方案有使用前提,使用过程中不能修改
field_list内部的元素。frozen=True仅禁止给字段重新赋值,列表本身的可变性没有被限制,如果修改了列表内的元素,已经生成的哈希值会失效,导致set、dict等结构出现逻辑错误。
内容的提问来源于stack exchange,提问作者T-Dawg
相关产品推荐
相关产品推荐

