我正在尝试编写一个调用自身的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,但我认为这不重要吗?
答案 0 :(得分:19)
也许你需要一个Y组合器?
编辑 - 使其成为Z组合子(我没有意识到Y组合器更适合按名称调用)
中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)