我尝试创建一个包含多个列表的列表,这些列表以这种方式填充相同的值:
l1 = [[False] * n] * m
没有任何错误,乍一看它看起来像列表的有效列表(print(l1) for n=m=3 : [[False,False,False],[False,False,False],[False,False,False]]
)
但是当我尝试l1[0][0] = True
时,我得到了一个奇怪的行为 - 列表已变为[[True,False,False],[True,False,False],[True,False,False]]
。
那么,为什么这样的列表初始化结果呢?我该怎么做才能正确创建一个列表?
答案 0 :(得分:3)
l1 = [[False] * n] * m
# I assume this is what you did, since
# [False * 3] == [0], and not [False, False, False]
采用相同 list
个实例[False * n]
m次。更改对所述实例的一个引用将影响所有引用。使用理解来创建独立列表:
l1 = [[False] * n for _ in range(m)]
应该注意这是有效的,因为bool
是不可变类型。如果你有一个可变类型,让我们说X
,你也必须使用对内部列表的理解:
l1 = [[X() for _ in range(n)] for _ in range(m)]
答案 1 :(得分:2)
那是因为实际上只有一个嵌套列表。您在外部列表中看到的实际上是三个引用实际上是相同的列表。
如果您使用自定义对象,则可以轻松地观察到这一点:
class MyClass:
def __init__(self):
pass
a = MyClass()
l = [[a] * 2]
打印l
会产生以下输出:
[<__main__.MyClass object at 0x000000000462A2E8>, <__main__.MyClass object at 0x000000000462A2E8>]
注意内存地址是如何相同的,因为它是同一个对象。它只是在列表中引用了两次。通过一个索引修改它与通过另一个或直接修改它相同。更改它会随处更新。
同样,当您通过执行l1[0][0] = True
修改嵌套列表时,对列表对象的所有引用都会更新,从而导致您看到的内容。