You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NumPy数组追加到列表时第二次操作修改首个条目的原因

两种代码结果差异的根本原因

差异和你操作的元素是不是NumPy类型没有关系,核心是Python的变量引用规则,加上NumPy数组属于可变对象的特性,两段代码里对E的操作本质完全不同:

  • 第一段代码里的E = H是变量重绑定操作
  • 第二段代码里的E[0,0] = H[0,0]是对象原地修改操作

第一段代码的执行流程

  1. 初始化时E = np.zeros((2,2)),变量E指向内存中一块存储全0二维数组的空间,第一次执行L.append(E)时,列表L的第0位存的是这块全0数组内存的引用。
  2. 执行E = H时,只是把变量E的指向,从原来的全0数组,改成了H所指向的全1数组的内存地址。这时候原来的全0数组并没有被改动或者回收,因为L[0]还持有它的引用,和现在E指向的全1数组是两块完全独立的内存空间。
  3. 第二次L.append(E)存的是全1数组的引用,两个列表元素指向完全不同的对象,自然互不影响,输出符合预期。

第二段代码的执行流程

  1. 初始化和第一次append的逻辑和第一段完全一致:E和L[0]同时指向那块存全0数组的内存空间。
  2. 执行E[0,0] = H[0,0]时,没有对变量E做任何重绑定,而是直接修改E当前指向的数组的内部内容:把这块内存里(0,0)位置的值从0改成1。因为L[0]和E指向的是同一块内存,修改这块内存的内容后,所有指向这块内存的引用读到的值都会同步变化。
  3. 第二次L.append(E)存的还是同一块数组内存的引用,相当于L里两个元素都指向同一个数组,打印出来自然两个位置都是修改后的[[1., 0.],[0., 0.]]。

补充说明:你提到的E.copy()之所以安全,是因为copy操作会开辟一块新的内存空间,把原数组的内容复制过去生成一个独立的新数组。把新数组的引用存入列表后,后续不管怎么修改原E指向的数组内容,都不会影响新内存里的副本,也就不会出现值被意外篡改的问题。

内容的提问来源于stack exchange,提问作者lisa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 15:00:55