当我执行以下命令时,我希望获得一个3x3矩阵(列表列表),其中所有单元格为零,中央单元格为1。相反,我得到一个矩阵,其中[0] [1],[1] [1]和[2] [1]位置都是一个:
a = [[0]*3]*3
a[1][1] = 1
这似乎表明矩阵中的所有单元格都指向同一个对象,这可以通过a[0] is a[1]
返回“True”这一事实得到证实。实际上,如果在上面的第二个表达式之前执行,a[0][0] is a[0][1]
也会返回“True”。那么,为什么不是[0] [0],[0] [2]等(第一和第三“列”中的单元格)也用新值更新?
答案 0 :(得分:5)
以下内容将满足您的期望:
a = [[0]*3 for i in range(3)]
问题在于,在您的示例中,a
的三个顶级元素最终引用了相同的列表,因此当您更改a
的一行时,所有其他行似乎也会更改。
我建议的代码通过为a
行创建三个单独的列表来进行更改。
答案 1 :(得分:3)
这是其中一个most common Python questions ever的变体,但由于此处的实际问题
那么,为什么不是[0] [0],[0] [2]等(第一和第三中的单元格) “列”)也用新值更新?
有点不同,我不会投票结束。
这是因为a[0] is a[1]
和a[0][0] is a[0][1]
略有不同。第一个是做你认为它正在做的事情:它检查两个列表a[0]
和a[1]
是否是相同的列表 - 这两个列表是否是同一个列表的两个名称。但是,第二个问题不是检查a[0][0]
和a[0][1]
是否指向列表中的相同条目 - 它是说a[0][0]
引用的对象 },即整数0,与a[0][1]
引用的对象相同,也是0.
这实际上可以返回False。实际上它返回True,因为CPython重用了小整数对象,但这并不能保证。
所以你的两个“是”检查不完全相同:虽然它们都测试引用对象的身份,但第二个测试在这种情况下没有相同的指针式含义。
答案 2 :(得分:0)
a [0] [0]是[0] [1]比较该指数的值(零)。它是相同的(整数)对象。
但是[0] [1] = 1会更改[0] [1]位置指向的对象。 包含列表a a [0]不会改变,只有指向的内容才会改变。
如果将索引视为对象的引用,则非常清楚。 a [0] [0]是[0] [1]意味着两者都引用相同的对象。 a [0] [1] = 1表示设置索引以引用“1”integet对象。