Python中列表复制后追加与直接追加原列表的行为差异问题
问题原因分析
核心问题是Python中列表为可变对象,memo缓存存储的是列表的内存引用而非独立值拷贝,你之前认为「第11行调用bestSum返回的是全新列表」的认知是错误的:只有target=0时返回的是全新空列表,其余场景返回的都是memo中已缓存的列表引用。
代码复现
# given a target sum and a list of numbers, find the # smallest combination that yields the target sum def bestSum(target, num, memo={}): # line 1 if target in memo: return memo[target] if target < 0: return None # line 5 if target == 0: return [] else: best_sum = None for i in range(len(num)): # line 10 remainder = bestSum(target - num[i], num, memo) if remainder != None: remainder = [r for r in remainder] # line 13 remainder.append(num[i]) # line 14 #remainder.append(num[i]) # line 15 if best_sum == None or len(remainder) < len(best_sum): best_sum = remainder #end for memo[target] = best_sum return best_sum #end def # to test the function print(bestSum(100, [25, 5], memo={}))
两种写法的运行差异
1. 启用第13、14行,注释第15行(正常运行)
- 第13行的列表推导式会对
remainder做一次浅拷贝,生成一个和memo中缓存列表完全独立的新列表 - 第14行的
append操作仅修改新生成的拷贝列表,不会改动memo中已经缓存的子问题结果 - 所有子问题的缓存结果不会被后续操作污染,计算逻辑符合预期,最终返回正确结果。
2. 启用第15行,注释第13、14行(结果错误)
- 没有做列表拷贝,直接对
remainder(即memo中缓存的子问题列表引用)执行append操作,会直接修改memo里存储的子问题结果 - 例如第一次计算
bestSum(5)得到结果[5]存入memo,后续某次流程拿到这个引用执行append(25)后,memo中缓存的bestSum(5)结果就被篡改成为[5,25],后续所有依赖bestSum(5)的计算都会得到错误值,最终整体结果完全不符合预期。
内容的提问来源于stack exchange,提问作者Deo
相关产品推荐
相关产品推荐

