Python自定义类实例存入set后仍有重复值,该如何修复代码?
问题原因
你自定义的Item类的__eq__方法仅执行了属性比较操作,没有返回布尔值,默认返回None(逻辑上等价于False)。而Python的set去重逻辑为:先判断两个对象的__hash__返回值是否相等,若相等再调用__eq__判断是否返回True,两个条件同时满足才会判定为同一对象进行去重,因此你当前的代码即使hash值一致也无法识别重复实例。
修复步骤
- 修正
__eq__方法,返回所有属性的与比较结果,同时补充类型校验避免和非Item实例比较时报错 - 补充缺失的
math库导入(你代码中调用了math.isnan)
修复后完整代码
import math class Item(): __name = "" __cost = 0 __gender = "" __prime = "" def has_all_properties(self): return bool(self.__name and not math.isnan(self.__cost) and self.__gender and self.__prime) def clean(self): return bool(self.__name and self.__cost <=20 and self.__gender == "male" and self.__prime == "yes") def __init__(self, name, cost, gender, prime): self.__name = name self.__cost = cost self.__gender = gender self.__prime = prime def __eq__(self, other): # 先判断比较对象是否为Item实例 if not isinstance(other, Item): return False # 返回所有属性的比较结果 return self.__name == other.__name and self.__cost == other.__cost and self.__gender == other.__gender and self.__prime == other.__prime def __hash__(self): return hash((self.__name, self.__cost, self.__gender, self.__prime)) def __repr__(self): return f"Item({self.__name},{self.__cost},{self.__gender},{self.__prime})" def __tuple__(self): return self.__name, self.__cost, self.__gender, self.__prime # 测试用的示例array from numpy import nan array = [['comic', 20.0, 'male', 'yes'], ['paint', 14.0, 'male', 'no'], ['pen', 5.0, 'female', 'yes'], ['phone case', 9.0, 'female', 'no'], ['headphone', 40.0, 'male', 'yes'], [None, 17.0, 'male', 'yes'], ['pencil ', 40.0, 'female', 'yes'], ['coat', nan, 'male', 'yes'], ['underwear', 15.0, 'male', 'yes'], ['shorts', 17.0, 'female', 'no'], ['goggles', 25.0, 'male', 'no'], ['comic', 20.0, 'male', 'yes'], ['watch', 55.0, 'male', 'yes'], ['notebook', 10.0, 'female', 'no'], ['mug', 58.0, 'male', 'no'], ['UNO', 15.0, None, None]] mylist = {Item(*k) for k in array} # 此时mylist中仅会保留1个comic对应的Item实例,重复项已被去除 print(mylist) filtered = filter(Item.has_all_properties, mylist) clean = filter(Item.clean, filtered) result = list(clean) # print(result)
验证效果
修复后运行代码,原array中两个重复的['comic', 20.0, 'male', 'yes']元素生成的实例会被set正确识别为同一对象,仅保留一份。
内容的提问来源于stack exchange,提问作者zhangruibo101
相关产品推荐
相关产品推荐

