You need to enable JavaScript to run this app. Python版can_sum函数记忆化优化后全测试输出为True的问题排查
优惠活动
大模型
产品
解决方案
定价
更多

Python版can_sum函数记忆化优化后全测试输出为True的问题排查

核心问题定位

出现计算结果不符合预期的根本原因,是Python可变默认参数的初始化机制和JavaScript存在本质差异,并非求和判断逻辑本身出错。
你在JS中给函数设置默认空对象参数时,每次函数调用都会在独立的执行上下文中新建一个空对象做缓存;但Python中,函数定义阶段就会仅创建一次memo={}这个空字典对象,后续所有没有显式传入memo的函数调用,全都会复用同一个全局字典实例——上一次函数调用存入的缓存值根本不会被清空,直接导致跨调用的结果污染。

异常结果的触发逻辑
  • 第一次调用can_sum(7,[2,3])执行完成后,memo字典中已经存储了递归过程中计算的所有中间值结果,包括键7对应的True值
  • 第二次调用can_sum(7,[7,5,3,4])时,函数入口会直接检查7 in memo,直接从老缓存中取出True返回,完全不会执行后续的求和判断逻辑
  • 第三次调用can_sum(7,[2,4]),本应返回False,却因为老缓存中已经存在键7对应的True值,直接返回缓存结果,和你实际观察到的“所有输出都是True”的现象完全匹配
  • 最后调用的can_sum(300,[7,14]),也是因为缓存中早已存在递归过程命中的中间值结果,不会重新基于当前传入的数字列表计算正确结果
    注:你代码中重复写了两次if targetSum<0判断,属于冗余代码,并非导致异常的原因,可直接删除。
修复方案

规避Python可变默认参数共享问题的标准写法是:将memo的默认值设置为None,在函数内部判断到memo为None时,再为当前这次独立的计算任务新建独立的空缓存字典,从根源上避免不同调用之间的缓存污染。
修复后的完整代码如下:

def can_sum(targetSum, numbers, memo=None):
    # 仅当没有传入自定义memo时,为当前计算任务新建独立空缓存
    if memo is None:
        memo = {}
    if targetSum < 0:
        return False
    if targetSum in memo:
        return memo[targetSum]
    if targetSum == 0:
        return True
    for n in numbers:
        remainder = targetSum - n
        if can_sum(remainder, numbers, memo):
            memo[targetSum] = True
            return True
    memo[targetSum] = False
    return False

修复后逐次调用的结果完全和预期一致:

  • can_sum(7,[2,3]) → True
  • can_sum(7,[7,5,3,4]) → True
  • can_sum(7,[2,4]) → False
  • can_sum(8,[2,3,5]) → True
  • can_sum(300,[7,14]) → False

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.04 09:45:05