操作员分配的列表列表不能引用特定的列表元素



>我正在设置一个以相同行开头的二维矩阵。 当我使用 lines=n*[list(string(] 创建列表列表以创建相同字符列表的 n 个列表时,它似乎有效。 但是当我尝试为行中的元素分配特定值时,它会复制到所有行中。

我在Jupyter Notebook中做了以下操作。 将显示代码和输出。 我还打印了矩阵中特定元素的 id((,同时试图弄清楚发生了什么。 如果我用乘法设置矩阵,所有行似乎都在同一个地址。 对元素进行赋值会更改所有行。 当我对列表进行硬编码时,元素以相同的地址开头,但是当我进行分配时,地址会发生变化。

Python真的应该这样工作吗?

这是不起作用的...

lines=11*[list('   |   |   ')] # Initialize matrix a list of lists
lines[0][0]='0'
for i in lines: print(i)
print('address of 0,0: '+str(id(lines[0][0])))
print('address of 1,0: '+str(id(lines[1][0])))
print('address of 2,0: '+str(id(lines[2][0])))

输出。。。

['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
address of 0,0: 2043952387048
address of 1,0: 2043952387048
address of 2,0: 2043952387048

这是有效的方法...

lines=[[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '], # Initialize matrix with data.
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '],
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '],
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '],
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '],
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '],
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '],
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '],
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '],
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' '],
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']]
lines[0][0]='0'
for i in lines: print(i)
print('address of 0,0: '+str(id(lines[0][0])))
print('address of 1,0: '+str(id(lines[1][0])))
print('address of 2,0: '+str(id(lines[2][0])))

输出。。。

['0', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
[' ', ' ', ' ', '|', ' ', ' ', ' ', '|', ' ', ' ', ' ']
address of 0,0: 2043952387048
address of 1,0: 2043951596632
address of 2,0: 2043951596632

当你这样做时

lines=11*[list('   |   |   ')]

你只给list(' | | ')打电话一次。它创建一个列表,并且同一列表被引用 11 次。它相当于:

temp = list('   |   |   ')
lines = 11*[temp]

只有一个temp列表,这将创建一个包含对该列表的 11 个引用的列表。将列表相乘只会复制容器的外部结构,而不会复制它引用的对象。

用:

lines = [list('   |   |   ') for _ in range(11)]

因此,它将调用list()11 次,每次创建一个新列表。

这个问题真的困扰着我,我终于在文档中找到了答案。 文档甚至说,"这经常困扰着新的Python程序员;......" 它是如何工作的写在这里,https://docs.python.org/3.6/library/stdtypes.html#typesseq-common

此"功能"在注释 2 中与"s * n 或 n * s"表条目一起进行了完整描述。

但是,我认为文档中有关" s + t"表条目的遗漏。 注6和7适用于此。 也许需要添加类似于 2 的注释? 原因是因为当您运行以下代码时,您会得到相同的行为...

s=[[1,2,3]]
s = s + s
s[0][0]=4
print(s)

输出为"[[4, 2, 3], [4, 2, 3]]"。

这个并没有那么困扰我,因为我期待它。

最新更新