Python 列表列表:为什么更改[1][0]处的值也会更改[0][0]?

Python 列表列表:为什么更改[1][0]处的值也会更改[0][0]?,python,list,Python,List,有人能解释一下这里发生了什么吗?我知道pythonints是通过值(而不是引用)赋值的 这可能有帮助(只需在每行转储list和a的值): 这段代码的一个不直观之处可能是,[0]*3似乎做了您期望的事情,而[[0]*3]*4没有做。为此,我只能猜测(还不是Python大师)一个单一长度的int列表是以一种似乎直观的方式处理的,而列表列表又回到了复制方式。没问题[[0]*3]*4创建了一个包含3个元素的列表的4个副本的列表。[0]、[1]、[2]和[3]都指向同一个列表 >>> a

有人能解释一下这里发生了什么吗?我知道python
int
s是通过值(而不是引用)赋值的

这可能有帮助(只需在每行转储
list
a
的值):


这段代码的一个不直观之处可能是,
[0]*3
似乎做了您期望的事情,而
[[0]*3]*4
没有做。为此,我只能猜测(还不是Python大师)一个单一长度的int列表是以一种似乎直观的方式处理的,而列表列表又回到了复制方式。

没问题<代码>[[0]*3]*4创建了一个包含3个元素的列表的4个副本的列表。[0]、[1]、[2]和[3]都指向同一个列表

>>> a=[[0]*3]*4
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0]='hello'
>>> a
[['hello', 0, 0], ['hello', 0, 0], ['hello', 0, 0], ['hello', 0, 0]]
>>> for mylist in a:
    ...     print id(a)
    ...
    42701168
    42701168
    42701168
    42701168
>>>

问题是外部列表包含同一内部列表值的多个副本。以下是您可以判断的方法:

a = [[0]*3]*4
print(a[0] is a[1]) # prints True
如果您想要一个二维的零列表,我建议对外部部分使用列表理解,以便获得单独的内部列表实例:

a = [[0]*3 for _ in range(4)]
print(a[0] is a[1]) # prints False

a[0][0]=1
print(a[1][0]) # prints 0

当您使用
*
符号创建列表时,您正在重复相同的元素。不是元素的副本,而是完全相同的对象

当您重复的对象是不可变的时,例如整数,您不会注意到

当对象是可变的(例如列表)时,会重复相同的列表。如果你改变了一个列表,你就是在改变所有的列表


在您的案例中,您对元素
[1]
进行了更改,这反映在元素
[0]

主题外:将变量命名为保留字(列表)会导致灾难:-)列表对象的不同程度低于预期:
[]*x
不会形成“深度副本”。问题是,如果我编辑[1][0]我不希望[0][0]采用相同的值。列表问题已得到解决,原因是不要为变量使用内置名称,即
list
+1@MarkRansom。那也是!马克,我想我们都会同意你的。但这一评论显然更适合OP。这张海报只是试图用OP自己的术语帮助OP理解。我意识到在最初的问题中是这样的,但你应该在回答中加以修正。好吧,我确实希望一次只访问一个元素。那我该怎么办?好吧,这就解释了一切!我必须说这种语法相当混乱。
a = [[0]*3]*4
print(a[0] is a[1]) # prints True
a = [[0]*3 for _ in range(4)]
print(a[0] is a[1]) # prints False

a[0][0]=1
print(a[1][0]) # prints 0