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
相关产品推荐
相关产品推荐

