python中嵌套列表的意外行为

python中嵌套列表的意外行为,python,list,Python,List,我有一个名为basic的嵌套列表,我想更改其中一个条目。我假设了以下行为: expected = [ [9],[0] ] unexpected = [ [9],[9] ] basic = [ [0],[0] ] basic[0][0] = 9 print(basic == expected) # this is true 然而,稍微修改一下就会得到令人惊讶的结果: l = [0] modified = [ l, l ] modified[0][0] = 9 print(modified ==

我有一个名为
basic
的嵌套列表,我想更改其中一个条目。我假设了以下行为:

expected = [ [9],[0] ]
unexpected = [ [9],[9] ]
basic = [ [0],[0] ]
basic[0][0] = 9
print(basic == expected) # this is true
然而,稍微修改一下就会得到令人惊讶的结果:

l = [0]
modified = [ l, l ]
modified[0][0] = 9
print(modified == expected) # this is false
print(modified == unexpected) # this is true
如果列表是以第二种方式定义的,则赋值会将整列设置为9

这种行为是故意的吗?若然,原因为何?我在文档中找不到任何关于它的信息。

在您的第一个示例中:

basic = [ [0],[0] ]
您已经创建了一个包含两个不同列表对象的列表对象。您可以通过
id()
或标识看到它们是不同的对象:

assert id(basic[0]) != id(basic[1])

assert basic[0] is not basic[1]
在第二个示例中:

l = [0]
modified = [ l, l ]
您已将同一列表对象放置到另一个列表中两次。两个列表标记均指同一对象:

assert id(basic[0]) == id(basic[1])

assert basic[0] is basic[1]
所以,是的。这就是变量(以及它们指向的对象)在Python中的工作方式

要获得预期的行为,需要创建单独的列表对象:

modified = [ l.copy(), l.copy() ]
在您的第一个示例中:

basic = [ [0],[0] ]
您已经创建了一个包含两个不同列表对象的列表对象。您可以通过
id()
或标识看到它们是不同的对象:

assert id(basic[0]) != id(basic[1])

assert basic[0] is not basic[1]
在第二个示例中:

l = [0]
modified = [ l, l ]
您已将同一列表对象放置到另一个列表中两次。两个列表标记均指同一对象:

assert id(basic[0]) == id(basic[1])

assert basic[0] is basic[1]
所以,是的。这就是变量(以及它们指向的对象)在Python中的工作方式

要获得预期的行为,需要创建单独的列表对象:

modified = [ l.copy(), l.copy() ]

我推荐阅读+1@jornsharpe,我正在寻找那个链接!我推荐阅读+1@jornsharpe,我正在寻找那个链接!