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

Python中能否实现无组合子的匿名递归?

Python中的匿名递归实现(非不动点组合子方案)

Python本身没有像APL的∇、JS的arguments.callee或R的Recall这类原生语法支持匿名函数直接引用自身,但可以通过自定义包装器实现类似需求,无需依赖Y组合子这类不动点组合子。

方案一:栈帧注入式包装器

通过inspect模块操作调用栈帧,将递归函数自身注入到lambda的局部命名空间中,让lambda可以通过指定名称(比如ano_rec)调用自身:

import inspect

def ano_rec_wrapper(func):
    def wrapper(*args, **kwargs):
        frame = inspect.currentframe()
        try:
            # 将当前递归函数注入到lambda的局部变量,命名为ano_rec
            frame.f_back.f_locals['ano_rec'] = wrapper
        finally:
            del frame  # 清理栈帧引用,避免循环泄漏
        return func(*args, **kwargs)
    return wrapper

使用示例

# 定义阶乘函数,无需显式引用自身名称
fact = ano_rec_wrapper(lambda n: 1 if n == 0 else n * ano_rec(n - 1))
print(fact(5))  # 输出:120

# 甚至可以直接调用,无需赋值给变量
print(ano_rec_wrapper(lambda n: 1 if n == 0 else n * ano_rec(n - 1))(5))  # 输出:120

这个方案完全符合你给出的示例形式,lambda内部通过ano_rec引用自身,无需知道最终赋值的变量名。

方案二:参数传递式包装器

如果不想依赖inspect模块,可以让lambda额外接收一个代表自身的参数,包装器自动传递这个参数:

class AnoRec:
    def __call__(self, func):
        self._func = func
        return self._recurse
    
    def _recurse(self, *args, **kwargs):
        # 将递归函数自身作为参数传递给lambda
        return self._func(*args, ano_rec=self._recurse, **kwargs)

使用示例

fact = AnoRec()(lambda n, ano_rec: 1 if n == 0 else n * ano_rec(n - 1))
print(fact(5))  # 输出:120

这种方式更稳妥,兼容性更好,但需要lambda额外声明一个接收自身的参数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 09:35:09