递归技术问询:为何第4行代码相似的两个函数结果差异巨大?
递归代码“同行不同果”的核心原因拆解
兄弟,我太懂这种盯着两行看起来完全一致的代码,却看着运行结果天差地别时的抓狂感了!递归的坑往往就藏在代码上下文的细微差异里,哪怕一行代码文本一模一样,只要它在函数里的「位置、作用域、后续逻辑」变了,结果就会完全不同。
我给你拆解几个最常见的原因,结合例子你就能秒懂:
1. 递归调用的时机:是「先执行代码再递归」还是「先递归再执行代码」
比如这两个版本,第4行都是sum += n,但执行顺序完全相反:
版本I(先累加再递归):
def calc_sum(n, sum): if n == 0: return sum sum += n # 第4行:先把当前n加到sum里,再递归处理n-1 return calc_sum(n-1, sum)调用
calc_sum(3, 0)的过程是:sum=0+3=3→ 递归calc_sum(2,3)→sum=3+2=5→ 递归calc_sum(1,5)→sum=5+1=6→ 递归calc_sum(0,6)返回6,最终结果是6。版本II(先递归再累加):
def calc_sum(n, sum): if n == 0: return sum res = calc_sum(n-1, sum) # 先递归到底,再执行第4行 sum += n # 第4行:这里修改的是当前栈帧的sum,和递归返回的res没关系! return res调用
calc_sum(3,0)的过程是:先递归到calc_sum(0,0)返回0,然后回到n=1的栈帧,执行sum +=1(但返回的是之前的res=0),再回到n=2的栈帧,sum +=2还是返回0,最终结果是0。
你看,第4行代码完全一样,但因为它在递归调用的前后位置不同,作用完全失效!
2. 返回值的处理:有没有把递归结果传递回来
再比如另一种常见情况,第4行相同,但版本II漏了返回递归调用的结果:
- 版本I:
def calc_sum(n, sum): if n <=0: return sum sum +=n # 第4行 return calc_sum(n-1, sum) # 把递归结果返回 - 版本II:
版本II里,除了最底层的递归返回sum,上层的函数都没有返回值,最终会得到def calc_sum(n, sum): if n <=0: return sum sum +=n # 第4行 calc_sum(n-1, sum) # 只调用递归,没返回!None,和版本I的正确结果完全不同。
3. 变量的作用域:是传值还是传引用(或可变对象的差异)
如果你的递归函数里用了可变对象(比如列表),哪怕第4行代码一样,也可能因为栈帧对变量的修改方式不同导致结果差异:
- 版本I(传不可变的int):
def calc_sum(n, sum): if n ==0: return sum sum +=n # 第4行:这里创建了新的int对象,不会影响上层栈帧的sum return calc_sum(n-1, sum) - 版本II(传可变的list):
虽然第4行看起来都是“累加”,但一个是修改不可变对象的副本,一个是直接修改共享的可变对象,最终结果的计算逻辑也会不一样。def calc_sum(n, sum_list): if n ==0: return sum_list[0] sum_list[0] +=n # 第4行:修改的是同一个列表对象,所有栈帧都共享这个修改 return calc_sum(n-1, sum_list)
总结一下:递归函数的行为从来不是由单独一行代码决定的,你得把终止条件、代码执行顺序、返回值传递、变量作用域这几个要素放在一起看。如果还是理不清,把两个版本的完整代码贴出来,我帮你逐行拆解栈帧的变化!
内容的提问来源于stack exchange,提问作者John DeBord
相关产品推荐
相关产品推荐

