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

3 投票
5 回答
1921 浏览
提问于 2025-04-16 05:21
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是什么?它是一个函数还是一个变量?

5 个回答

0
rec_fn = lambda: 10==11 or rec_fn()
rec_fn()

一个函数的内容在执行之前是不会被计算的。一开始,rec_fn是没有值的。这个lambda表达式里面只是一些对rec_fn这个变量的函数调用的表达式。因为函数还没被执行,所以不会出错。接着,这个新的lambda函数被赋值给变量rec_fn,然后调用这个函数。现在因为函数正在被执行,它会执行到函数调用的那一步。这个表达式是10==11 or rec_fn()。这是一个or表达式,所以先计算左边的部分。10==11是假的,所以必须计算右边的部分,也就是调用某个函数(或者其他可调用的对象)rec_fn。在这个时候,rec_fn被赋值为我们刚刚创建的函数(它自己),所以它会被递归调用。如此循环下去。这个过程可以理解为:

def rec_fn():
    return 10==11 or rec_fn()

lambda可以使用任意数量的参数。在lambda: ...的情况下,没有指定任何参数,所以它是一个“没有参数的函数”。

记住,函数(包括lambda)都是一等公民。你可以像对待其他对象一样传递它们,也可以把它们存储到其他变量中。

rec_fn = lambda: ...

这样是可以的,因为你定义了一个lambda函数并把它存储在变量rec_fn中。你可以像调用其他函数一样,通过这个名字rec_fn()来调用它。

rec_fn() = lambda: ...

而这样就会失败,因为你不能把任何东西赋值给函数调用rec_fn()的结果。

以这种方式定义函数和正常的函数定义是很不同的:

def rec_fn2(): # here you may use the parens with the name to indicate it takes no arguments
    ...        # unlike in the lambda assignment above

只要记住这个区别就可以了。

0

这是一个可能更容易理解的递归例子,使用了阶乘的lambda版本:

fact = lambda x: 1 if x == 0 else x*fact(x-1)
prin(fact(10))

输出结果:

3628800

不过要注意,Python有递归的限制哦。

这是使用或的例子,类似于if..else的写法:

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)
4

可以把函数调用想象成一个操作符。因为它确实是这样。当你写 rec_fn() 的时候,其实你在做两件事。首先,你在获取一个名为 rec_fn 的对象的引用。这个对象恰好是一个函数,但这并不重要(在Python中,除了函数之外的对象也可以被调用)。然后有 (),它的意思是“调用我刚才提到的那个对象”。你可以在不调用函数的情况下获取它的引用,只需省略括号,然后你可以给它起不同的名字,任何一个名字都可以通过加上括号来调用它。

def func1():
   print "func1"

func2 = func1

func2()       # prints "func1"

现在你可以看到lambda是怎么工作的。

func3 = lambda x: x+1

你做的事情和上面 func2 = func1 的那一行是一样的,只不过lambda表达式就是那个函数。语法只是不同;lambda函数可以在不命名的情况下定义。

lambda可以有任意数量的参数,所以 lambda: 3 是一个不接受任何参数并且总是返回3的函数,而 lambda x, y: x+y 是一个接受两个参数并返回它们和的函数。

至于 or 的用法,它利用了短路的特性。基本上,or 知道如果它的第一个操作数是 True,那么就不需要计算第二个,因为结果无论第二个参数是什么都会是 True。所以你可以把它理解为 if not 10==11: rec_fn()。顺便提一下,and 也有短路的特性,不过它是在第一个参数是 False 的时候短路,因为它知道无论第二个参数是什么,结果都会是 False

撰写回答