python中不希望出现的列表分配行为

python中不希望出现的列表分配行为,python,list,Python,List,当我执行以下命令时,我希望得到一个3x3矩阵(列表列表),其中所有单元格为零,中心单元格为一。相反,我得到一个矩阵,其中[0][1]、[1][1]和[2][1]位置都是一个: a = [[0]*3]*3 a[1][1] = 1 这似乎表明矩阵中的所有单元格都指向同一个对象,这一点可以通过以下事实得到证实:a[0]是[1]返回“True”。实际上,a[0][0]是[0][1]如果在上面第二个表达式之前执行,也会返回“True”。那么,为什么[0][0]、[0][2]等(第一列和第三列中的单元格)

当我执行以下命令时,我希望得到一个3x3矩阵(列表列表),其中所有单元格为零,中心单元格为一。相反,我得到一个矩阵,其中[0][1]、[1][1]和[2][1]位置都是一个:

a = [[0]*3]*3
a[1][1] = 1

这似乎表明矩阵中的所有单元格都指向同一个对象,这一点可以通过以下事实得到证实:
a[0]是[1]
返回“True”。实际上,
a[0][0]是[0][1]
如果在上面第二个表达式之前执行,也会返回“True”。那么,为什么[0][0]、[0][2]等(第一列和第三列中的单元格)没有用新值进行更新呢?

以下内容将满足您的期望:

a = [[0]*3 for i in range(3)]
问题在于,在您的示例中,
a
的三个顶级元素最终引用了同一个列表,因此当您更改
a
的一行时,所有其他行似乎也会更改


我提议的代码改变了这一点,通过为
a

的行创建三个单独的列表,这是其中一个的变体,但由于这里的实际问题

那么,为什么a[0][0]、a[0][2]等(第一个和第三个单元格中的单元格)不存在呢 “列”)是否也使用新值更新

有点不同,我不会投票结束

这是因为
a[0]是[1]
a[0][0]是[0][1]
有点不同。第一个是做你认为它在做的事情:它检查两个列表,
a[0]
a[1]
是否是同一个列表——它们是否是同一个列表的两个名称。不过,第二个问题并不是检查
a[0][0]
a[0][1]
是否指向列表中的同一条目,而是检查
a[0][0]
引用的对象,即整数0,是否与
a[0][1]
引用的对象相同,后者也是0

这实际上可能返回False。实际上,它返回True,因为CPython重用小整数对象,但这不能保证


因此,您的两个“是”检查并不完全相同:虽然它们都测试引用对象的标识,但在这种情况下,第二个测试没有相同的指针式含义。

a[0][0]是a[0][1]正在比较此索引处的值(零)。它是相同的(整数)对象

但是[0][1]=1会更改[0][1]位置指向的对象。 包含列表a[0]不会更改,只有指向的内容会更改

如果将索引视为对象的引用,这是非常清楚的。 [0][0]是[0][1]表示两者引用同一对象。


[0][1]=1表示将索引设置为引用“1”整数对象。

谢谢。这很有用,但不能回答最后一个问题。这正是我想要的。这是一个非常微妙的区别!