有人可以为我解释这种行为吗?
mapping = dict.fromkeys([1, 2, 3], [])
objects = [{'pk': 1}, {'pk': 2}, {'pk': 3}]
for obj in objects:
pk = obj['pk']
mapping[pk].append(obj)
print mapping
# expected: {1: [{'pk': 1}], 2: [{'pk': 2}], 3: [{'pk': 3}]}
# got: {1: [{'pk': 1}, {'pk': 2}, {'pk': 3}], 2: [{'pk': 1}, {'pk': 2}, {'pk': 3}], 3: [{'pk': 1}, {'pk': 2}, {'pk': 3}]}
我正在尝试将objects
中的词组映射到另一个词典,其词的键是原始词典的属性。假设objects
列表包含每个唯一PK的几个对象(我之前不仅仅使用map
的原因)。
答案 0 :(得分:5)
那是因为在:
mapping = dict.fromkeys([1, 2, 3], [])
[]
被评估一次,因此每个键与值具有相同的列表。请尝试使用collections.defaultdict
。
答案 1 :(得分:1)
如果按以下方式更改mapping
:
from collections import defaultdict
mapping = defaultdict(list)
并按原样保留其余部分,代码将按预期执行。
您当前代码的问题是mapping
的所有三个键都映射到同一个列表。当你将一个元素附加到一个元素时,你实际上是将它附加到所有元素。
答案 2 :(得分:1)
它发生了,因为在这一行中:
mapping = dict.fromkeys([1, 2, 3], [])
为每个键分配相同的列表。并且由于列表是可变的,通过修改一个键的列表,您可以同时修改其他键的列表。
答案 3 :(得分:1)
在第1行,使用表达式[]会导致创建一个空列表。
这是上面代码段中出现的唯一空列表对象。当dict.fromkeys运行时,它不会为空列表创建三个不同的副本。相反,它对SAME空列表进行了三次引用。
因此,在稍后的循环中,每次在空列表中添加另一个数字时,它都是相同的列表。