制作矩阵副本(列表列表)后,为什么对副本进行双索引会更改原始副本,而索引却没有呢?

时间:2020-06-14 13:57:37

标签: python-3.x

我有一个定义为全局变量的矩阵:

BOARD = [
    [0, 0, 3],
    [2, 0, 0],
    [0, 0, 0]
]

但是,在处理此矩阵时,我希望保持原样不变,而是处理副本。所以我在main函数中这样做是为了制作独立副本:

board = BOARD[:]

如预期的那样,board == BOARDboard is BOARD的结果分别为TrueFalse。因此,当我像这样board[0] = [1, 0, 3]进行编辑时,仅更改了board,这很好。但是,如果我做board[0][0] = 1,那么BOARD也会改变,这不是我期望的。而且仍然很陌生,board is BOARD仍然是False

为什么会有这种不一致的行为,以及关于如何解决该问题的任何建议?

编辑:

如果我跑步:

board = BOARD[:]
board[0] = [1, 0, 3]
board[0][0] = 2

然后BOARD不变。

但是我只添加了单个索引进行比较。在实际程序中,我希望能够做到这一点:

board = BOARD[:]
board[0][0] = 2

但这就是BOARD确实发生变化的地方,即使我希望它保持不变。

2 个答案:

答案 0 :(得分:1)

我没有收到此错误。这是我的代码:

BOARD = [
[0, 0, 3],
[2, 0, 0],
[0, 0, 0]
]

board = BOARD[:]
print(board == BOARD) # prints True
board[0] = [1,0,3]
print(board == BOARD) # prints False
board[0][0] = 1 
print(board == BOARD) # still prints False

在阅读AkThao的说明后,我了解发生了什么。

Python使用指针来实现列表。 例如,如果您设置了a = [1,2,3]b = a。如果您随后修改b[0] = 5,则a也将被修改,因为a和b都是指向相同存储位置的指针。

2D列表是使用指向指针的指针(双指针)来实现的,即[p1,p2,p3]之类的指针列表。

当您执行board = BOARD[:]时,它会创建列表的副本,但是不会更改指针(列表的元素)的实际值。因此,列表板实际上只是3个不同指针值的副本。

这就是为什么当您执行board [0] [0] = 1时,它也会同时更改BOARD的值的原因(因为board存储的实际指针未更改)。

像我一样完成board[0] = [1, 0, 3]时,您正在更改指针的实际值,这就是为什么原始BOARD之后不会更改的原因。

答案 1 :(得分:0)

为什么BOARD会完全改变?

BOARD和b都是引用。

编码vec = b时,将b地址分配给BOARD。因此,更改b中的数据也将“更改” BOARD。

我还尝试了每种方法来复制列表,但是一种方法成功了,

b=copy.deepcopy(BOARD)

尽管deepcopy对于大型列表来说很耗时,您可以尝试一下。

import copy
B = [
    [0, 0, 3],
    [2, 0, 0],
    [0, 0, 0]
]
print(B)

b=copy.deepcopy(B)

b[0][0] = 2

print(b)

print(B)

输出:

[[0, 0, 3], [2, 0, 0], [0, 0, 0]]
[[2, 0, 3], [2, 0, 0], [0, 0, 0]]
[[0, 0, 3], [2, 0, 0], [0, 0, 0]]

希望这对您有帮助!