为何以下Python代码触发无限递归错误?如何修复?
问题描述
以下是编写的Python代码:
def aoeu(): r = lambda: 5 s = r r = lambda: s() * 6 s = r r = lambda: s() // 2 print(r())
运行时触发递归错误:
File "/Users/nyap/tasks/spreadsheet/spreadsheet/aoeu.py", line 10, in <lambda> r = lambda: s() * 6 ^^^ [Previous line repeated 993 more times] RecursionError: maximum recursion depth exceeded
尝试以下方式后仍出现相同问题:
- 使用
s = copy.deepcopy(r) - 定义无参函数:
def s(): return r()
- 定义带参函数:
def s(r): return r()
疑问:该错误的原因是什么?能否在不新增变量的情况下修复(实际代码存在循环逻辑)?
环境:Python 3.12.6
原因分析
核心问题是Python的lambda和函数采用延迟绑定变量的机制——它们不会在定义时绑定变量的当前值,而是在被调用时才去查找变量的最新值。
拆解代码执行逻辑:
r = lambda:5:r指向一个返回5的lambdas = r:s与r指向同一个lambdar = lambda: s() *6:这个新lambda里的s并未绑定此时的s(即返回5的lambda),而是要等到调用时才会查找s的当前值s = r:s现在指向步骤3中定义的lambda(lambda: s()*6)r = lambda: s()//2:这个lambda同样延迟绑定s,调用时才会读取s的最新值
调用r()时的递归链:
- 执行
lambda: s()//2,此时s是步骤4中的lambda(lambda: s()*6) - 调用该lambda时,它会查找当前的
s值——还是它自己,于是进入无限递归,最终触发RecursionError
copy.deepcopy无效是因为复制的是函数对象,但函数内部的变量绑定逻辑依然是延迟的;后两种定义s的方式同理,要么是引用后续被覆盖的r,要么是参数传递逻辑未解决绑定时机问题。
修复方法(不新增变量)
要解决延迟绑定问题,需让lambda在定义时就捕获变量的当前值,可以利用Python默认参数在函数定义时求值的特性实现:
修改后的代码:
def aoeu(): r = lambda: 5 s = r r = lambda s=s: s() * 6 # 用默认参数捕获当前s的取值 s = r r = lambda s=s: s() // 2 # 同样用默认参数捕获当前s的取值 print(r())
执行后输出15,计算逻辑:
- 最终调用的
r()是lambda s=s: s()//2,这里的s是步骤4中定义的lambda s=s: s()*6 - 调用该s时,它的默认参数s是步骤2中的
lambda:5,因此执行5*6=30 - 最后
30//2=15得到结果
这种方式未新增额外变量,仅通过默认参数特性,让lambda在定义时就绑定当时的变量值,避免了调用时的动态查找。
内容的提问来源于stack exchange,提问作者Noel Yap
相关产品推荐
相关产品推荐

