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

Python中值相等的两种2D数组初始化为何产生不同结果

核心差异根源:底层引用的共享机制
  • 两种初始化的实际内存逻辑差异
    • 列表推导式实现:dp = [[float('inf') for _ in range(k+1)]for _ in range(n+1)] 每一轮外层循环都会生成一个独立的、内存地址互不相同的子列表,每一行的存储完全隔离,修改任意一行的元素不会影响其他行。
    • 列表乘法实现:dp1 = [[float('inf')]*(k+1)]*(n+1) 运算本质是将*运算符前生成的单个子列表的内存引用重复复制n+1次,整个二维列表的所有行,全部指向内存中同一个子列表对象,不存在逐行独立的存储结构。
  • 为什么assert校验会通过
    Python的列表相等判断会逐元素逐一比对值。由于乘法生成的所有行本就是同一个对象,所有位置的初始值均为float('inf'),与列表推导式生成的数组初始值完全一致,因此dp == dp1的判断会返回真值,完全检测不出底层的引用差异,这也是问题极具迷惑性的核心原因。
  • 为什么DP输出会出现本质偏差
    动态规划求解过程需要按节点、按剩余通行额度逐次更新二维数组的状态值。使用乘法初始化的数组时,任意一行任意位置的元素修改,都会同步影响所有行的同位置值。
    可以通过极简代码验证这个效果:
    n = 3
    k = 2
    bad_dp = [[float('inf')]*(k+1)]*(n+1)
    # 校验所有行的内存地址是否一致
    print(id(bad_dp[0]) == id(bad_dp[1]) == id(bad_dp[2]))  # 输出True,证明三行是同一个对象
    bad_dp[0][0] = 100
    print(bad_dp[1][0])  # 输出100,而非初始的inf,证明修改是全局同步的
    
    问题中出现的全0输出,本质就是乘法初始化的结构让所有行的状态被反复同步覆盖——原本按节点独立存储的最短路数值完全串值,状态转移逻辑完全失效,最终不管走到哪个节点,读取到的都是被同步覆盖的0值,自然输出全0;而列表推导式初始化的结构因为行与行完全隔离,状态可以独立转移计算,才能得到正确的0 0 0 2 2结果。
  • 常见认知误区澄清
    一维列表的乘法如[0]*5可以正常使用,因为其存储的是整数这类不可变对象;但只要嵌套结构中存在列表这类可变对象,直接在外层使用列表乘法,就必然会触发引用共享的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 07:36:04