我试图初始化一个空列表的字典以便附加到它们,但是这导致了一些奇怪的行为:
def solution(A):
d = dict.fromkeys(set(A), [])
for i in range(len(A)):
d[A[i]].append(i)
print(d)
输入:
[3, 4, 3, 2, 3, -1, 3, 3]
输出:
{2: [0, 1, 2, 3, 4, 5, 6, 7],
3: [0, 1, 2, 3, 4, 5, 6, 7],
4: [0, 1, 2, 3, 4, 5, 6, 7],
-1: [0, 1, 2, 3, 4, 5, 6, 7]}
dict.fromkeys
似乎将所有列表初始化为指向内部相同列表的指针,这是怎么回事?我怎么知道这是行为/为什么会是行为?有没有办法告诉口译员不要这样做?
答案 0 :(得分:1)
所有列表都是同一个对象。 []
只是一个文字表达式,在传递给dict.fromkeys
之前会先求值。函数如何知道如何复制任何随机对象?
如果您想要这种行为,请选择一个collections.defaultdict
:
from collections import defaultdict
def solution(A):
d = defaultdict(list) # `list` is a factory funtion that can be called repeatedly
for i in range(len(A)):
d[A[i]].append(i)
print(d)
# or, if you dislike the output (note, it is a dict already)
# print(dict(d))
答案 1 :(得分:1)
我怎么知道这是行为
Python documentation says it并警告您:
来自键的类方法(可迭代 [,值])
使用 iterable 中的键并将值设置为 value 。创建新词典。
fromkeys()
是返回新字典的类方法。 value 默认为None
。所有的值仅涉及一个实例, 因此通常将 value 当作可变对象是没有意义的 例如空列表。要获取不同的值,请使用dict 而是理解。
答案 2 :(得分:0)
在fromkeys中,如果提供的值是可变的(如列表),则每个键的值都将引用同一对象,因此所有值都将立即更新。您可以通过将其附加到原始列表中来进行测试,以产生与得到的结果相同的结果:
def solution(A):
lst = []
d = dict.fromkeys(set(A), lst)
for i in range(len(A)):
lst.append(i)
print(d)
除了提供其他答案外,您还可以使用字典理解路线:
def solution(A):
d = { key : [] for key in A }
for i in range(len(A)):
d[A[i]].append(i)
print(d)