Python嵌套列表添加元素时条目被覆盖的问题及解决
问题:迭代生成嵌套字典列表时,所有元素被最后一个条目覆盖怎么解决?
我最近写了一段代码,想把serializer里的数据整理成嵌套的购物列表字典,逻辑是初始化一个字典,然后循环迭代数据,把每个条目添加到嵌套数组里。代码是这样的:
list = {"shopping_list": []} item = {} count = 0 stuff = json.loads(serializer.data["stuff_file"]) for s in stuff: item["level"] = count item["position"] = count * 10 item["item_name"] = s["name"] list["shopping_list"].append(item) count += 1
本来预期能得到每个元素都唯一的列表,结果却所有元素都被最后一个条目覆盖了,比如实际输出是:
{ "shopping_list": [ { "level": 2, "position": 20, "item_name": "Bronze Badge" }, { "level": 2, "position": 20, "item_name": "Bronze Badge" }, { "level": 2, "position": 20, "item_name": "Bronze Badge" } ] }
我想要的正确结果应该是这样的:
{ "shopping_list": [ { "level": 0, "position": 0, "item_name": "Gold Badge" }, { "level": 1, "position": 10, "item_name": "Silver Badge" }, { "level": 2, "position": 20, "item_name": "Bronze Badge" } ] }
问题根源
这是Python里引用类型的典型坑:你在循环外面只创建了一个item字典对象,每次循环只是修改这个字典的键值对,然后把它的引用添加到列表里。列表里的所有元素其实指向的是同一个字典,最后循环结束时,这个字典的内容是最后一次修改的结果,自然所有条目都一模一样了。
解决方法
只要把item = {}移到循环内部,让每次迭代都创建一个全新的字典对象就行:
list = {"shopping_list": []} count = 0 stuff = json.loads(serializer.data["stuff_file"]) for s in stuff: # 每次循环新建空字典,避免复用同一个引用 item = {} item["level"] = count item["position"] = count * 10 item["item_name"] = s["name"] list["shopping_list"].append(item) count += 1
或者用更简洁的写法,直接在循环里生成字典字面量,还能借助enumerate自动维护计数器,省掉手动的count变量:
list = {"shopping_list": []} stuff = json.loads(serializer.data["stuff_file"]) for count, s in enumerate(stuff): list["shopping_list"].append({ "level": count, "position": count * 10, "item_name": s["name"] })
这样修改后,每个添加到列表里的都是独立的字典对象,各自保留对应的键值对,就不会出现覆盖问题了。
内容的提问来源于stack exchange,提问作者AbreQueVoy
相关产品推荐
相关产品推荐

