递归lambda表达式可能吗?

时间:2009-07-29 21:54:24

标签: python recursion lambda

我正在尝试编写一个调用自身的lambda表达式,但我似乎找不到任何语法,或者即使它是可能的。

基本上我想把以下函数转移到下面的lambda表达式中:(我意识到它是一个愚蠢的应用程序,它只是添加,但我正在探索我可以用python中的lambda表达式做什么)

def add(a, b):
   if a <= 0:
      return b
   else:
      return 1 + add(a - 1, b)

add = lambda a, b: [1 + add(a-1, b), b][a <= 0]

但是调用lambda形式的add会导致运行时错误,因为达到了最大递归深度。甚至可以在python中执行此操作?或者我只是犯了一些愚蠢的错误?哦,我正在使用python3.0,但我认为这不重要吗?

6 个答案:

答案 0 :(得分:19)

也许你需要一个Y组合器?

编辑 - 使其成为Z组合子(我没有意识到Y组合器更适合按名称调用)

使用Wikipedia

中Z组合子的定义
>>> Z = lambda f: (lambda x: f(lambda *args: x(x)(*args)))(lambda x: f(lambda *args: x(x)(*args)))

使用它,您可以将add定义为完全匿名的函数(即在其定义中没有引用其名称)

>>> add = Z(lambda f: lambda a, b: b if a <= 0 else 1 + f(a - 1, b))
>>> add(1, 1)
2
>>> add(1, 5)
6

答案 1 :(得分:8)

也许您应该尝试Z combinator,此示例来自:{/ p>

>>> Z = lambda f: (lambda x: f(lambda *args: x(x)(*args)))(lambda x: f(lambda *args: x(x)(*args)))
>>> fact = lambda f: lambda x: 1 if x == 0 else x * f(x-1)
>>> Z(fact)(5)
120

答案 2 :(得分:6)

首先,递归lambda表达式是完全没必要的。正如您自己所指出的,对于lambda表达式来调用自身,它需要有一个名称。但lambda表达式只不过是匿名函数。因此,如果给lambda表达式一个名称,它不再是lambda表达式,而是一个函数。

因此,使用lambda表达式是没用的,只会让人迷惑。所以用def创建它。

但是,正如您自己发现的那样,lambda表达式可以是递归的。你自己的例子是。事实上它是如此奇妙的递归,你超过了最大递归深度。所以这是递归的好。你的问题是你总是在表达式中调用add,所以递归永远不会停止。不要那样做。你的表达式可以这样表达:

add = lambda a, b: a > 0 and (1 + add(a-1, b)) or b

负责解决这个问题。但是,你的第一个def是正确的做法。

答案 3 :(得分:3)

add = lambda a, b: b if a <= 0 else 1 + add(a - 1, b)

答案 4 :(得分:0)

你想要Y组合子,或其他fixed point combinator

这是一个Python lambda表达式的示例实现:

Y = lambda g: (lambda f: g(lambda arg: f(f)(arg))) (lambda f: g(lambda arg: f(f)(arg)))

像这样使用它:

factorial = Y(lambda f: (lambda num: num and num * f(num - 1) or 1))

也就是说,将一个单参数函数(或lambda)传递给Y(),该函数接收自身的递归版本作为参数。所以函数不需要知道它自己的名字,因为它得到了对它自己的引用。

请注意,这对于add()函数来说确实很棘手,因为Y组合器仅支持传递单个参数。您可以通过currying获得更多参数 - 但我会将其作为练习留给读者。 : - )

答案 5 :(得分:0)

有点晚......但我刚发现这个宝石@ http://metapython.blogspot.com/2010/11/recursive-lambda-functions.html

def myself (*args, **kw):
    caller_frame = currentframe(1)
    code = caller_frame.f_code
    return  FunctionType(code, caller_frame.f_globals)(*args,**kw)

print "5! = "
print (lambda x:1 if n <= 1 else myself(n-1)*n)(5)