这个 Python Lambda 递归表达式是如何工作的?
rec_fn = lambda: 10==11 or rec_fn()
rec_fn()
我是 Python 新手,正在尝试了解 lambda 表达式的工作原理。有人可以解释一下这个递归是如何工作的吗?我能够理解 10==11 将是“假”,这就是 rec_fn 将被一次又一次递归调用的方式。
但我无法理解这种看似新的编写 lambda 表达式的方法。
lambda x: x+y 发生了什么,其中有一个参数“x”进入未命名函数?
另外,为什么是
rec_fn() = lambda: .... // a syntax error
rec_fn = lambda: .... //syntactically correct - WHY?
rec_fn?它是函数还是变量?
rec_fn = lambda: 10==11 or rec_fn()
rec_fn()
I am new to Python and trying to understand how lambda expressions work. Can somebody explain how this recursion is working? I am able to understand that 10==11 will be 'false' and that's how rec_fn will be called again and again recursively.
But what I am not able to get is this seemingly new way of writing a lambda expression.
whatever happened to lambda x: x+y
where there is a parameter 'x' going into the unnamed function?
Also, why is
rec_fn() = lambda: .... // a syntax error
rec_fn = lambda: .... //syntactically correct - WHY?
What is rec_fn? Is it a function or a variable?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
将函数调用视为运算符可能会有所帮助。因为这就是它的本质。当你执行rec_fn()时,你正在做两件事。首先,您将获得对名为
rec_fn
的对象的引用。这恰好是一个函数,但这并不重要(在Python中,除了函数之外的对象都是可调用的)。然后是()
,意思是“调用我刚刚命名的对象”。可以在不调用函数的情况下获取对函数的引用,只需去掉括号即可,然后您可以为其分配不同的名称,然后可以通过添加以下名称来使用其中任何名称来调用它:括号。现在您可以看到 lambda 是如何工作的。
您所做的操作与上面的
func2 = func1
行相同,只是 lambda 表达式是函数。只是语法不同而已;无需命名即可定义 lambda 函数。Lambda 可以有任意数量的参数,因此 lambda: 3 是一个不带参数且始终返回 3 的函数,而 lambda x, y: x+y 是一个函数它接受两个参数并返回它们的总和。
至于
or
的使用方式,它利用了短路。基本上,or
知道它的第一个操作数是否是True
,它不需要计算第二个参数,因为无论第二个参数是什么,结果都将为True
。因此,您可以将其读作if not 10==11: rec_fn()
。顺便说一句,和
也会短路,尽管如果第一个参数是False
,它就会短路,因为它知道结果将为False
不管第二个参数是什么。It may help to think of a function call as an operator. Because that's what it is. When you do
rec_fn()
you are doing two things. First, you're getting a reference to the object namedrec_fn
. This happens to be a function, but that doesn't matter (in Python, objects besides functions are callable). Then there is()
which means "call the object I just named." It is possible to get a reference to a function without calling it, just by leaving off the parentheses, and then you can assign it different names, any of which can then be used to call it by adding the parentheses.Now you can see how the lambda works.
You are doing the same as the
func2 = func1
line above, except the lambda expression is the function. The syntax is just different; the lambda function can be defined without giving it a name.Lambdas can have any number of parameters, so
lambda: 3
is a function that takes no parameters and always returns 3, whilelambda x, y: x+y
is a function that takes two parameters and returns their sum.As to the way
or
is being used, it's taking advantage of short-circuiting. Basically,or
knows that if its first operand isTrue
, it doesn't need to evaluate the second, because the result is going to beTrue
regardless of what the second argument is. You could thus read this asif not 10==11: rec_fn()
. By the way,and
also short-circuits, although it does so if the first argument isFalse
since it knows that the result will beFalse
regardless of what the second argument is.与此表达式类似,但是此表达式需要一个参数,
而您正在调用一个没有参数的函数,因此没有 x 这是rec_fn(),
这是尝试设置函数调用rec_fn()的结果(右有侧面表达)到一个值。那里没有变量可以分配 lambda 函数。
这里的rec_fn是保存lambda的变量(本质上就像一个函数指针)
is the similar to this expression, however this one requires a parameter,
whereas you'r rec_fn() with you're calling a function with no parameters hence no x
This is trying to set result of the function call rec_fn() (a right had side expression) to a value. There is no variabele there to assign the lambda function to.
here rec_fn in the variable that holds the lambda (in essence like a function pointer)
函数调用 -
x()
- 是一个表达式。这是赋值左侧的合法语法结构。应该发生什么? (这与42 = lambda: ....
大致相同)在第二种情况下,您只需分配创建的新函数对象(使用
lambda
关键字) 到变量(名为rec_fn
)并且不调用函数。也许更清晰的方法是使用(首选)非 lambda 嵌套函数方法:
lambda
关键字只是一个语法快捷方式,可以用作表达式的一部分。在上述情况下,rec_fn 是一个局部变量(假设所述代码嵌套在函数/方法中)。
rec_fn
变量存储一个函数对象,稍后可以使用()
调用该函数对象。方法大致相同(可以调用的函数),但它们是属性而不是变量。A function invocation --
x()
-- is an expression. It is lot a legal syntax construct on the left side of an assignment. What should happen? (It is roughly the same as saying42 = lambda: ....
)In the 2nd case, you are simply assigning the new function object created (with the
lambda
keyword) to a variable (namedrec_fn
) and not invoking a function.Perhaps a more clear way is to use the (preferred) non-lambda nested function approach:
The
lambda
keyword is just a syntactic shortcut which can be used as part of an expression.rec_fn
is a local variable in the above cases (assuming said code is nested in a function/method). Therec_fn
variable stores a function object which can later be invoked with()
. Methods are roughly the same (functions which can be invoked), but they are properties and not variables.函数体在执行之前不会被求值。一开始,
rec_fn
没有值。 lambda 的内容只是一些对某个变量rec_fn
进行函数调用的表达式。它还不会失败,因为该函数尚未执行。然后将新的 lambda 函数分配给变量rec_fn
,然后调用该函数。现在,由于该函数正在执行,因此它将执行直到函数调用为止的动作。表达式为10==11或rec_fn()
。它是一个or
表达式,因此计算左侧。10==11
为 False,因此它必须评估右侧,即对某个函数(或其他可调用对象)rec_fn
的函数调用。此时,rec_fn
被分配给我们刚刚创建的函数(本身),因此它被调用(递归)。等等。它相当于:可以根据需要使用任意多个参数来编写 Lambda。对于 lambda: ... ,没有指定任何内容,因此它是一个“不带参数的函数”。
请记住,函数(以及扩展的 lambda)是第一类对象。您可以像任何其他对象一样传递它们并将它们存储到其他变量中。
没问题,因为您已经定义了一个 lambda 函数并将其存储到变量
rec_fn
中。可以像调用任何其他函数一样使用该名称rec_fn()
来调用它。另一方面会失败,因为您无法将任何内容分配给函数调用
rec_fn()
的结果。以这种方式定义函数与普通函数定义有很大不同:
只需尝试记住差异即可。
The body of a function is not evaluated until it is executed. At the start,
rec_fn
has no value. The contents of the lambda is just some expression that has some function call on some variablerec_fn
. It won't fail yet because the function isn't executed yet. The new lambda function is then assigned to the variablerec_fn
followed by a call to the function. Now since the function is being executed, it will go through the motions up to the function call. The expression is10==11 or rec_fn()
. It's anor
expresison so the left hand side is evaluated.10==11
is False so it must evaluate the right hand side which is a function call to some function (or other callable object)rec_fn
. At that point,rec_fn
is assigned to the function we just created (itself) so it gets called (recursively). And so on. It is equivalent to:Lambdas can be written using as many parameters as necessary. In the case of
lambda: ...
, there are none specified so it's a "function that takes no arguments."Just remember, functions (and by extension, lambdas) are first class objects. You can pass them around like any other object and store them into other variables.
is fine because you've defined a lambda function and stored it into the variable
rec_fn
. It can be called by using that namerec_fn()
like you would any other function.on the other hand fails because you cannot assign anything to the result of the function call
rec_fn()
.Defining a function this way is much different than a normal function definition:
Just try to remember the difference.
这可能是更容易理解的递归、阶乘 lambda 版本的示例:
输出:
不过,请注意 Python 的递归限制。
使用 or 作为 if..else 的示例:
This is maybe more understandable example of recursion, factorial lambda version:
Output:
Be aware of Python's recursion limit, though.
Example of using or as this if..else: