Python自定义字典子类时如何正确去除列表值中的重复元素
问题原因
你重写的__setitem__方法覆盖了字典原生的赋值逻辑:所有针对键的赋值操作,无论传入什么值,都会固定执行「如果键不存在就初始化空列表,再把传入值追加到对应列表末尾」的流程。
当你遍历字典执行d[k] = list(set(v))时,传入的去重后列表不会替换原有值,反而会被当成单个新元素追加到原列表尾部,才会输出[1, 2, 1, 1, [1, 2]]的错误结果。
修复方案
保留原有重复键自动追加值到列表的特性,新增专门用于直接覆写键值的方法,去重赋值时调用该方法绕过追加逻辑即可:
class Dictlist(dict): def __setitem__(self, key, value): try: self[key] except KeyError: super(Dictlist, self).__setitem__(key, []) self[key].append(value) # 直接覆写键值,走原生字典赋值逻辑 def overwrite(self, key, value): super().__setitem__(key, value) d = Dictlist() d['test'] = 1 d['test'] = 2 d['test'] = 1 d['test'] = 1 print(d) # 输出 {'test': [1, 2, 1, 1]} for k, v in d.items(): # 保序去重,不需要保序可替换为 list(set(v)) unique_val = list(dict.fromkeys(v)) d.overwrite(k, unique_val) print(d) # 输出 {'test': [1, 2]}
提示:
set去重会打乱原有值的顺序,Python 3.7及以上版本用dict.fromkeys()可以实现保序去重。
内容的提问来源于stack exchange,提问作者Rikky Bhai
相关产品推荐
相关产品推荐

