这个Python Lambda递归表达式是如何工作的?

这个Python Lambda递归表达式是如何工作的?,python,recursion,lambda,Python,Recursion,Lambda,我是Python新手,试图理解lambda表达式是如何工作的。有人能解释一下这个递归是如何工作的吗?我能够理解10==11将是“false”,这就是rec_fn将一次又一次递归调用的方式 但我无法得到的是,这种书写lambda表达式的新方法 lambda x:x+y在未命名函数中有参数“x”时发生了什么 还有,为什么会这样 rec_fn = lambda: 10==11 or rec_fn() rec_fn() 什么是rec_fn?它是函数还是变量?函数调用--x()--是一个表达式。在赋值的

我是Python新手,试图理解lambda表达式是如何工作的。有人能解释一下这个递归是如何工作的吗?我能够理解10==11将是“false”,这就是rec_fn将一次又一次递归调用的方式

但我无法得到的是,这种书写lambda表达式的新方法

lambda x:x+y
在未命名函数中有参数“x”时发生了什么

还有,为什么会这样

rec_fn = lambda: 10==11 or rec_fn()
rec_fn()
什么是rec_fn?它是函数还是变量?

函数调用--
x()
--是一个表达式。在赋值的左边有很多合法的语法结构。该怎么办?(这大致相当于说
42=lambda:…

在第二种情况下,只需将创建的新函数对象(使用
lambda
关键字)分配给变量(名为
rec\u fn
),而不调用函数

rec_fn = lambda: ...
也许更明确的方法是使用(首选)非lambda嵌套函数方法:

rec_fn() = lambda: .... // a syntax error
rec_fn = lambda: .... //syntactically correct - WHY?
lambda
关键字只是一个语法快捷方式,可以用作表达式的一部分

rec_fn
在上述情况下是局部变量(假设所述代码嵌套在函数/方法中)。
rec\u fn
变量存储一个函数对象,以后可以使用
()
调用该函数对象。方法大致相同(可以调用的函数),但它们是属性而不是变量

def rec_fn():
    return 10==11 or rec_fn()
与此表达式类似,但此表达式需要一个参数

  rec_fn = lambda: 10==11 or rec_fn()
  rec_fn()
而使用rec_fn()调用的函数没有参数,因此没有x

rec_fn = lambda x: 10==11 or rec_fn(x)
x = ...
rec_fn(x)
这试图将函数调用rec_fn()(右侧表达式)的结果设置为一个值。没有可分配lambda函数的变量

rec_fn() = lambda: .... // a syntax error
这里rec_fn位于保存lambda的变量中(本质上类似于函数指针)

函数体在执行之前不会进行求值。在开始时,
rec\u fn
没有值。lambda的内容只是对某个变量
rec\u fn
进行函数调用的某个表达式。它不会因为函数尚未执行而失败。然后将新的lambda函数分配给变量
rec\u fn
,然后调用该函数。现在,由于函数正在执行,它将经历一系列动作,直到函数调用。表达式是
10==11或rec\u fn()
。它是一个
表达式,因此对左侧进行求值
10==11
为False,因此它必须计算对某个函数(或其他可调用对象)的函数调用的右侧。此时,
rec\u fn
被分配给我们刚刚创建的函数(本身),因此它被(递归地)调用。等等这相当于:

rec_fn = lambda: 10==11 or rec_fn()
rec_fn()
可以根据需要使用任意多的参数编写lambda。在
lambda:…
的情况下,没有指定任何参数,因此它是一个“不带参数的函数”

请记住,函数(以及扩展后的lambda)是第一类对象。您可以像任何其他对象一样传递它们,并将它们存储到其他变量中

def rec_fn():
    return 10==11 or rec_fn()
很好,因为您已经定义了lambda函数并将其存储到变量
rec\u fn
中。可以像调用任何其他函数一样,使用该名称调用它

rec_fn = lambda: ...
另一方面,失败是因为无法为函数调用的结果分配任何内容
rec\u fn()

以这种方式定义函数与普通函数定义有很大不同:

rec_fn() = lambda: ...

试着记住其中的区别。

将函数调用视为运算符可能会有所帮助。因为事实就是这样。当你做
rec\u fn()
你在做两件事。首先,您将获得一个名为
rec\u fn
的对象的引用。这恰好是一个函数,但这并不重要(在Python中,函数之外的对象是可调用的)。然后是
()
,意思是“调用我刚刚命名的对象”。不调用函数就可以获得对函数的引用,只需去掉括号,然后可以为它指定不同的名称,然后可以通过添加括号来使用任何名称来调用它

def rec_fn2(): # here you may use the parens with the name to indicate it takes no arguments
    ...        # unlike in the lambda assignment above
现在您可以看到lambda是如何工作的

def func1():
   print "func1"

func2 = func1

func2()       # prints "func1"
您的操作与上面的
func2=func1
行相同,只是lambda表达式是函数。语法完全不同;可以定义lambda函数而不给它命名

lambda可以有任意数量的参数,因此
lambda:3
是一个不接受参数并始终返回3的函数,而
lambda x,y:x+y
是一个接受两个参数并返回其和的函数


至于
的使用方式,它利用了短路。基本上,
知道如果它的第一个操作数是
True
,它就不需要计算第二个操作数,因为不管第二个参数是什么,结果都是
True
。因此,如果不是10==11:rec\u fn(),您可以将其理解为
。顺便说一句,
也会短路,尽管如果第一个参数是
False
,它会短路,因为它知道结果将是
False
,而不管第二个参数是什么。

这可能是更容易理解的递归示例,阶乘lambda版本:

func3 = lambda x: x+1
输出:

fact = lambda x: 1 if x == 0 else x*fact(x-1)
prin(fact(10))
不过,请注意Python的递归限制

使用或作为此if..else的示例:

3628800

谢谢大家!你的解释太棒了:D但在我接受答案之前,我需要知道lambda内部发生了什么。条件结构“或”是如何工作的?这有点像if/else语句。“如果不是这样,那么就执行那种”是的,这件事肯定更容易理解。清除“如果/否则”st
print 1 or 'a'
print 'a' or False
print False or True or 0/9
fact_or = lambda x: x == 0 and 1 or x * fact_or(x-1)
print fact_or(10)