3

我在 Python 字典中看到一些不寻常的行为:

import numpy as np
td =[np.Inf, 2, 3]
a = {}
# First initialize contents of dictionary to a list of values
for k in range(10):
    a[k] = td

# now I want to access the contents to modify them based on certain criteria 
for k in range(10):
    c = a[k]
    c[0] = k
    a[k] = c

由此,我希望每个字典键值的列表的每个第一项都基于 ( c[0] = k) 进行更改,但是,我最后得到的是字典的所有值都更新为 的最后一个值k,如下所示:

{0: [9, 2, 3], 1: [9, 2, 3], 2: [9, 2, 3], 3: [9, 2, 3], 
 4: [9, 2, 3], 5: [9, 2, 3], 6: [9, 2, 3], 7: [9, 2, 3], 
 8: [9, 2, 3], 9: [9, 2, 3]}

我错过了什么,还是字典定义有问题?

我可以以不同的方式解决这个问题,让我的代码运行,但我对字典类为什么会这样表现感兴趣。

4

3 回答 3

9

因为每个键都获得相同的列表...要制作列表的浅表副本,请使用以下语法:

for k in range(10):
    a[k] = td[:] 

演示:

>>> d = {}
>>> el = [1, 2, 3]
>>> d[0] = el
>>> d[1] = el
>>> map(id, d.values())
[28358416, 28358416]
于 2012-11-21T17:13:32.997 回答
2

发生这种情况是因为当您将值插入 时dict,您并没有插入一个全新的列表。您实际上是在插入对同一个旧列表的引用。因此,当您更改一个值时,您实际上是在更改该值指向的列表,因此也更改了所有值指向的列表。

如果您真的想要为每个值单独列出列表,那么最好在插入时制作列表的浅表副本,如下所示:

td =[np.Inf, 2, 3]
for k in range(10):
    a[k] = td[:] #making a new list out of the old one

现在,这将按您期望的方式工作

for k in range(10):
    c = a[k]
    c[0] = k
    a[k] = c

希望这可以帮助

于 2012-11-21T17:15:30.860 回答
0

当您td在 line中引用时a[k] = td,您实际上是在将引用附加到原始列表。该列表的任何修改在任何地方都是可见的。您需要使用copy 模块来创建一个新列表(或在循环本身中为每个条目构建一个新列表):

for k in range(10):
    a[k] = [np.Inf, 2, 3]
于 2012-11-21T17:14:21.207 回答