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

Python3带记忆化的嵌套回溯函数:为何将mem作为参数传入可节省内存?

两种记忆化实现的内存差异根源
  • 你最初的实现使用了Python的闭包捕获机制:嵌套的recursiveWithMem直接引用外层作用域的mem变量,Python为了支持闭包引用,会为这个函数对象额外创建一组cell对象,专门用来保存跨作用域的变量引用,这部分是固定的额外内存开销。
  • 更关键的是对象生命周期的差异:LeetCode的测试运行时会把你的findTargetSumWays方法绑定到长期存在的Solution类实例上。你定义的闭包函数对象因为被外层方法的引用链持有,即使整个递归流程跑完,闭包关联的所有上下文(mem字典、外层捕获的nums数组、初始S值)都不会被垃圾回收,直到整个测试实例被销毁。
  • 把mem作为参数传入的版本里,recursiveWithMem完全没有引用外层的自由变量,不再是闭包函数:所有需要的取值(nums、S、mem)都是通过函数栈帧的参数传递,函数执行完毕栈帧就会被系统回收,不会和外层的Solution实例产生长期的对象绑定,因此没有这部分额外的常驻内存开销。

注:两个版本里的mem字典都是同一个共享对象,递归过程中所有分支都会读写同一份缓存数据,因此时间复杂度完全一致,你观察到的内存差异,和缓存本身的大小没有关系——实际存储的缓存键值对在两个版本里是完全一样的。

为什么@cache装饰器实现的内存占用更高
  • @cache属于Python标准库的装饰器,它会对原函数做两层包装:第一层是装饰器本身的缓存存储结构,第二层是带缓存逻辑的包装函数对象。这两层结构本身就比你手写的字典存储有更大的元数据开销。
  • 手写的mem字典只存储你实际用到的缓存键值对(键是(i, S)元组,值是整数计数),而@cache的内部实现会为每个缓存项额外存储调用参数的元数据、缓存状态标记,相同缓存量下的内存占用会远高于手写字典。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 22:45:01