Python列表乘法:[[…]] * 3使3个列表在修改时相互镜像

Python list multiplication: [[…]]*3 makes 3 lists which mirror each other when modified

本问题已经有最佳答案,请猛点这里访问。

为什么会这样?我不太明白:

1
2
3
4
5
6
>>> P = [ [()]*3 ]*3
>>> P
[[(), (), ()], [(), (), ()], [(), (), ()]]
>>> P[0][0]=1
>>> P
[[1, (), ()], [1, (), ()], [1, (), ()]]


您已对同一列表进行了3次引用。

1
2
3
4
>>> a = b = []
>>> a.append(42)
>>> b
[42]

您想这样做:

1
P = [[()] * 3 for x in range(3)]

你也可以这样写,这样可以显示[[()]*3]*3的结构。

1
2
3
4
>>> P=[i[:] for i in [[()]*3]*3]
>>> P[0][0]=1
>>> P
[[1, (), ()], [(), (), ()], [(), (), ()]

它也比使用范围稍快。从IPython外壳:

1
2
3
4
5
In [1]: timeit P = [ [()]*3 for i in range(3) ]
1000000 loops, best of 3: 1.41 us per loop

In [2]: timeit P=[i[:] for i in [[()]*3]*3]
1000000 loops, best of 3: 1.27 us per loop


列表是可变的,将列表乘以数字不会复制其元素。您可以尝试将其更改为列表理解,这样它将对[()]*3进行三次评估,从而创建三个不同的列表:

1
P = [ [()]*3 for i in range(3) ]

它实际上是同一个内部列表(同一个引用)重复了3次,所以当您修改其中任何一个列表时,实际上是修改了所有列表。

因此,内部列表[()]*3生成一个由三个元组组成的列表。但是这个列表会重复三次。但是,在python中,它实际上是一个被相乘的引用列表,因此引用是重复的,但是每个引用仍然指向同一个底层列表。