Python循环中使用.append()添加字典到列表后结果不符合预期的技术问询
为什么列表append字典后所有元素都变成最后一个值?
问题场景
你有如下的JSON数据列表:
myjson = [ {"GROUP" : "A", "TYPE" : "I", "VALUE1" : 25, "VALUE2" : 26, "REMARK" : "None"}, {"GROUP" : "B", "TYPE" : "II", "VALUE1" : 33, "VALUE2" : 22, "REMARK" : "None"} ]
目标是得到仅包含GROUP和TYPE键的字典列表:
[{'GROUP': 'A', 'TYPE': 'I'}, {'GROUP': 'B', 'TYPE': 'II'}]
你编写了这段代码:
temp = {} myjson2 = [] for listitem in myjson: for key, item in listitem.items(): if key == "GROUP" or key == "TYPE": temp[key] = item print(temp) myjson2.append(temp)
执行时print(temp)的输出符合预期:
{'GROUP': 'A', 'TYPE': 'I'} {'GROUP': 'B', 'TYPE': 'II'}
但print(myjson2)却得到了不符合预期的结果:
[{'GROUP': 'B', 'TYPE': 'II'}, {'GROUP': 'B', 'TYPE': 'II'}]
原因分析
这是Python中可变对象引用的经典问题:
- 你在循环外部只创建了一个
temp字典对象,它是可变类型(mutable)。 - 每次循环时,你并没有新建字典,只是修改了这个已有
temp字典里的键值对。 - 当你调用
myjson2.append(temp)时,并不是把temp的“副本”添加到列表里,而是把这个字典对象的引用(内存地址)添加进去了。 - 所以列表
myjson2里的两个元素,其实都指向同一个字典对象。最后一次循环修改了这个字典的内容,导致列表里所有元素看起来都是最后一次修改后的结果。
解决方案
方案1:每次循环创建新字典
把temp = {}放到循环内部,确保每次迭代都生成一个全新的字典对象:
myjson2 = [] for listitem in myjson: temp = {} # 每次循环新建一个独立的字典 for key, item in listitem.items(): if key == "GROUP" or key == "TYPE": temp[key] = item myjson2.append(temp)
方案2:用字典推导式简化代码
Python的推导式可以更简洁高效地实现需求,同时避免引用问题:
# 直接指定要保留的键 myjson2 = [{"GROUP": item["GROUP"], "TYPE": item["TYPE"]} for item in myjson] # 如果以后需要保留的键更多,用这种更灵活的方式 keys_to_keep = {"GROUP", "TYPE"} myjson2 = [{k: v for k, v in item.items() if k in keys_to_keep} for item in myjson]
执行上述任意方案后,print(myjson2)都会得到你预期的结果:
[{'GROUP': 'A', 'TYPE': 'I'}, {'GROUP': 'B', 'TYPE': 'II'}]
内容的提问来源于stack exchange,提问作者Alana
相关产品推荐
相关产品推荐

