Go语言中如何为递归函数实现独立有效的缓存装饰器?
解决递归函数装饰器缓存不生效的问题
问题核心是:递归函数fib内部调用的是全局作用域的原函数,而非被装饰后的版本,导致只有最外层调用被缓存,递归过程的结果没被存入缓存,缓存长度远低于预期。
以下是两种可行的解决方案:
方案1:修改全局作用域的函数引用
直接在main函数中把被装饰后的fib赋值给全局变量,让递归调用指向装饰后的函数,缓存即可正常收集所有递归过程的结果。
cache = {} def cached(func): def wrapper(n): if n not in cache: cache[n] = func(n) return cache[n] return wrapper def fib(n): if n <= 1: return n return fib(n-1) + fib(n-2) def main(): global fib fib = cached(fib) print(f"fib(40) = {fib(40)}") print(f"缓存长度: {len(cache)}") # 输出41,符合预期 if __name__ == "__main__": main()
方案2:用可变对象存储函数引用(不修改全局变量)
如果不想改动全局的fib函数,可以用一个可变对象(比如列表)来保存fib的引用,让函数内部调用这个可变对象里的函数,后续将装饰后的函数赋值给该对象即可。
cache = {} def cached(func): def wrapper(n): if n not in cache: cache[n] = func(n) return cache[n] return wrapper # 用列表存储函数引用,方便后续更新 fib_func = [None] def fib(n): if n <= 1: return n # 调用可变对象中存储的函数 return fib_func[0](n-1) + fib_func[0](n-2) # 初始化引用为原fib函数 fib_func[0] = fib def main(): cached_fib = cached(fib_func[0]) # 更新引用为装饰后的函数 fib_func[0] = cached_fib print(f"fib(40) = {cached_fib(40)}") print(f"缓存长度: {len(cache)}") # 输出41,符合预期 if __name__ == "__main__": main()
方案对比
- 方案1实现简单,适合不需要保留原
fib函数的场景,修改全局变量后,所有地方调用的都是装饰后的版本。 - 方案2更灵活,不会污染全局作用域,原
fib函数依然可以被单独调用,适合需要同时保留两个版本的场景。
内容的提问来源于stack exchange,提问作者De Scar
相关产品推荐
相关产品推荐

