在列表字典中更改一个python列表会改变所有列表

时间:2012-12-07 20:36:18

标签: python list dictionary

  

可能重复:
  Two separate python lists acting as one

此代码创建列表字典,密钥位于usens。列表中充满了0 s

usens = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 110, 111, 112, 113, 114,
         115, 116, 117, 118, 119, 302, 303, 306, 307, 308, 370, 371, 500,
         501, 1000, 1010, 1020, 1100, 1200, 1201, 1202, 2000, 2001, 2002
         ]
empty = [[0]*length]*len(usens)
data = dict(zip(usens, empty))
pprint.pprint(data, indent=5)

data[0][0] += 1
pprint.pprint(data, indent=5)

第一个漂亮的打印返回预期的(模糊已删除):

{0: [0, 0, 0, 0, 0],
 1: [0, 0, 0, 0, 0],
 2: [0, 0, 0, 0, 0],
 3: [0, 0, 0, 0, 0],
 4: [0, 0, 0, 0, 0],
 5: [0, 0, 0, 0, 0],
 .....
 2001: [0, 0, 0, 0, 0],
 2002: [0, 0, 0, 0, 0]}

然后我执行此操作:data[0][0] += 1,期望第一个列表(索引0)以1开头,但没有其他内容可以更改。

但是,所有列表都已修改:

{0: [1, 0, 0, 0, 0],
 1: [1, 0, 0, 0, 0],
 2: [1, 0, 0, 0, 0],
 3: [1, 0, 0, 0, 0],
 4: [1, 0, 0, 0, 0],
 .....
 2001: [1, 0, 0, 0, 0],
 2002: [1, 0, 0, 0, 0]}

为什么,以及如何制作,只修改了一个列表?

2 个答案:

答案 0 :(得分:3)

empty = [[0]*length]*len(usens)将创建同一列表的len(usens)个副本,这与具有相同内容的len(usens)列表不同。

尝试empty = [[0]*length for i in range(len(usens))]

答案 1 :(得分:1)

使用*创建副本;对于[0]它没关系,因为它正在复制一个不可变的标量;但外部*创建相同列表的副本(即复制引用)。你可以使用类似的东西:

empty = [0]*5
data = {n:list(empty) for n in usens}

(dict comprehension)创建你的列表(如果使用Python 2.7+)。使用list制作副本。