在列表中硬拷贝dicts

时间:2015-05-01 09:57:57

标签: python dictionary copy

当我尝试下面的列表创建时,我看到每个元素都引用了一个不同的对象。

>>> a = [1] * 7
>>> a[0] = 2
>>> a
Out[17]: [2, 1, 1, 1, 1, 1, 1]

但是,当我尝试使用词典创建以下列表时,我看到每个元素都引用同一个对象。

a = [{1:10, 2:20}] * 7
a[0][1] = 30
a
Out[20]: 
[{1: 30, 2: 20},
 {1: 30, 2: 20},
 {1: 30, 2: 20},
 {1: 30, 2: 20},
 {1: 30, 2: 20},
 {1: 30, 2: 20},
 {1: 30, 2: 20}]

如何尽可能简单地创建第二个列表,但是使用元素副本而不是引用?

2 个答案:

答案 0 :(得分:2)

>>> a = [{1:10, 2:20} for _ in range(7)]
>>> a[0][1] = 30
>>> a
[{1: 30, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}]

答案 1 :(得分:1)

实际上当你使用乘法创建一个列表时,python会创建一个包含相同内存地址的重复项的列表:

>>> a=[1]*7
>>> id(a[0])
40968536
>>> id(a[1])
40968536
>>> a = [{1:10, 2:20}]*7
>>> id(a[0])
140379402804592
>>> id(a[1])
140379402804592

但是当你想要改变像(数字,元组,字符串......)这样的不可变对象时,python会改变引用而不是对象!

当你改变一个可变对象时,python会改变对象本身,所以所有的条目都会改变。

因此,作为python 2中更有效的方法,您可以在列表理解中使用xrangexrange返回生成器而不是列表)(在3 range中)来创建列表:

>>> a = [{1:10, 2:20} for _ in xrange(7)]
>>> a
[{1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}]
>>> a[0][1]=0
>>> a
[{1: 0, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}, {1: 10, 2: 20}]

>>> id(a[0])
140379402734400
>>> id(a[1])
140379402809424