python-3.x - 在制作矩阵(列表列表)的副本后,为什么对副本进行双重索引会更改原始内容但索引不会?
问题描述
我有一个定义为全局变量的矩阵:
BOARD = [
[0, 0, 3],
[2, 0, 0],
[0, 0, 0]
]
但是,在操作此矩阵时,我想保持原件不变,而是在副本上工作。所以我在主函数中这样做是为了制作一个独立的副本:
board = BOARD[:]
正如预期的那样, 和 的结果分别是board == BOARD
和。因此,当我像这样进行编辑时,只会更改,这很好。但是,如果我这样做了,那么也会发生变化,这不是我所期望的。更奇怪的是,仍然是。board is BOARD
True
False
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
改变的地方,即使我希望它保持不变。
解决方案
我没有收到此错误。这是我的代码:
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 都是指向同一内存位置的指针。
二维列表是使用指向指针的指针(双指针)实现的,即像 [p1, p2, p3] 这样的指针列表。
当您这样做时board = BOARD[:]
,它会创建列表的副本,但不会更改指针的实际值(列表的元素)。因此,列表板本质上只是 3 个不同指针值的副本。
这就是为什么当你做 board[0][0] = 1 时,它也会改变 BOARD 的值(因为 board 存储的实际指针没有改变)。
当你board[0] = [1, 0, 3]
像我一样做时,你正在改变指针的实际值,这就是为什么原来的 BOARD 之后不会改变的原因。
推荐阅读
- wordpress - Wordpress - 发送有关发布元值更改的电子邮件
- c# - 不支持给定的路径格式;流作家
- wordpress - wordpress网站首页出现404错误
- angular - Accessibilty - 在 Angular 中更改路线时失去焦点
- c# - 从 ASP.Net Core 3.0 升级到 .net Core 3.1 后,IIS 托管的 Aps.Net API 失败
- kotlin - Kotlin:对嵌套属性使用 .contains()
- node.js - 如果我为 from 和 to 选择相同的日期,则不会获取数据
- java - ZonedDateTime ISO-8601 解析:为什么需要时区 ID 中的冒号?
- synchronization - 没有 vkQueuePresentKHR() 的 Vulkan 渲染完成同步
- c - 程序的 strtok 部分的越野车