使用list()执行dict键复制相同的列表会产生彼此的引用吗?

时间:2014-01-14 05:29:22

标签: python list dictionary

我似乎遇到了一个问题,我正在使用dict将一个模板列表复制到list()中的多个键,这样我就可以专门为使用{dict访问的给定列表更改值1}}键。但是,我似乎在操作复制列表的键的值。

list1 = [['x', 'y', 0],
        ['m', 'n', 0],
]

dict2 = {'first': list(list1),
        'second': list(list1),
}

def attempt(arg):
    dict_key = dict2[arg]
    for each in dict_key:
        each[2] += 1

attempt('first')
print dict2['first']
print dict2['second']

输出:

[['x', 'y', 1], ['m', 'n', 1]] # expect elems to contain 1 
[['x', 'y', 1], ['m', 'n', 1]] # expect elems to contain 2

看起来list()实际上并没有创建一个实际的副本,但是行为更像是一个赋值,但这对我来说没有意义。有人可以解释一下吗?

1 个答案:

答案 0 :(得分:3)

list()确实制作副本......但它是副本。当您致电a = list(b)时,a是一个全新的列表,但它指的是与b相同的对象。如果这些对象本身就是列表,那么你还没有完成你想做的事。

要执行“2级”复制,您只需使用列表解析:

a = [list(x) for x in b]

要执行一个完全向下的副本(也处理棘手的情况,比如字符串由字符串组成),请使用stdlib中的deepcopy函数。


为了调试这些事情,使用is运算符或id函数会有所帮助。例如:

>>> list1 = [['x', 'y', 0],
...         ['m', 'n', 0],
... ]
>>> dict2 = {'first': list(list1),
...         'second': list(list1),
... }
>>> id(dict2['first'])
4398414856
>>> id(dict2['second'])
4398414920
>>> id(dict2['first'][0])
4378407688
>>> id(dict2['second'][0])
4378407688

您可以很容易地看到firstsecond是两个不同的列表......但它们具有相同的第一个元素。


或者,或者,在交互式可视化工具中运行您的代码,例如this one