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

递归函数赋值与环境使用困惑:斐波那契函数场景解析

问题:递归斐波那契函数重赋值后,递归调用为何指向新函数?

我正在学习《Composing Programs》中的优化知识,写了三个函数:memo实现记忆化,count是统计调用次数的包装器,fib是递归版斐波那契函数。

代码如下:

def memo(f):
    cache = {}

    def memoized(n):
        if n not in cache:
            cache[n] = f(n)
        return cache[n]

    return memoized


def count(f):
    def counted(*args):
        counted.call_count += 1
        return f(*args)

    counted.call_count = 0
    return counted


def fib(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    return fib(n - 2) + fib(n - 1)

调用时,我先把count(fib)赋值给counted_fib用来统计调用次数,之后又把fib变量重新赋值为memo(counted_fib),不再指向原函数。

调用fib(19)时一切正常,但原函数里的递归语句return fib(n - 2) + fib(n - 1)触发的却是memo(counted_fib)版本的fib。我想不通为什么会这样,毕竟原函数是在后续赋值之前定义的。


解答

核心原因是Python中函数内部的变量引用是动态查找的,不是在函数定义时就绑定到当时的对象上。

具体拆解整个过程:

  • 原fib函数定义时,里面的fib只是一个名称,并没有和定义时的递归函数体绑定死。当代码执行到return fib(n-2)+fib(n-1)这一行时,Python会去当前作用域(这里是全局作用域)查找名为fib的对象,而非直接使用定义时的那个函数。
  • 执行counted_fib = count(fib)时,counted_fib指向包装了原fib的统计函数,但此时全局的fib还是最初的递归函数。
  • 当你执行fib = memo(counted_fib)后,全局名称fib的指向彻底改变——现在它指向memo返回的记忆化包装函数,不再是最初定义的递归函数。
  • 调用fib(19)时,先进入记忆化函数,缓存未命中时会调用counted_fib(统计包装函数),统计函数又会调用它内部保存的原fib函数。此时原fib函数执行到递归语句,去全局查找fib,找到的就是已经被重赋值的memo(counted_fib),所以递归调用的是这个优化后的版本。

简单来说:原函数里的fib是个“活”的名称,每次使用时才会查找当前对应的对象,而非绑定定义时的固定函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 08:05:22