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

为何以下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和函数采用延迟绑定变量的机制——它们不会在定义时绑定变量的当前值,而是在被调用时才去查找变量的最新值。

拆解代码执行逻辑:

  1. r = lambda:5:r指向一个返回5的lambda
  2. s = r:s与r指向同一个lambda
  3. r = lambda: s() *6:这个新lambda里的s并未绑定此时的s(即返回5的lambda),而是要等到调用时才会查找s的当前值
  4. s = r:s现在指向步骤3中定义的lambda(lambda: s()*6)
  5. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 15:35:57