用Python lambda函数计算数字的阶乘

10 投票
11 回答
27815 浏览
提问于 2025-04-17 19:02

我刚开始学习Python,遇到了lambda函数。在一个问题中,作者要求写一个一行代码的lambda函数来计算一个数字的阶乘。

这是给出的解决方案:

num = 5
print (lambda b: (lambda a, b: a(a, b))(lambda a, b: b*a(a, b-1) if b > 0 else 1,b))(num)

我看不懂这个奇怪的语法。a(a,b)是什么意思呢?

有人能解释一下吗?

谢谢!

11 个回答

6

让我们像剥洋葱一样,把这行代码拆开来看看。

print (lambda b: (Y))(num)

我们正在创建一个匿名函数(这里的关键词lambda表示我们要输入一系列参数名,然后是一个冒号,接着是一个使用这些参数的函数),然后把num传给它,以满足它的一个参数。

   (lambda a, b: a(a, b))(X,b)

在这个lambda内部,我们定义了另一个lambda。我们把这个lambda叫做Y。这个Y有两个参数,分别是a和b。a会用a和b来调用,所以a是一个可以调用自己的函数,同时还需要一个其他参数。

            (lambda a, b: b*a(a, b-1) if b > 0 else 1
            ,
            b)

这些是Y的参数。第一个是一个lambda函数,我们叫它X。我们可以看到X是一个计算阶乘的函数,而第二个参数将会是它的数字。

也就是说,如果我们回头看看Y,我们会看到我们将会调用:

X(X, b)

这将会执行

b*X(X, b-1) if b > 0 else 1

并且会自我调用,形成阶乘的递归部分。

再往外看,我们可以看到b就是我们传给最外层lambda的num。

num*X(X, b-1) if num > 0 else 1

这有点让人困惑,因为它写成了一行很复杂的代码 :)

7

就是这么简单:

n=input()

print reduce(lambda x,y:x*y,range(1,n+1))
10

阶乘的概念基本上是你想象中的样子。你可以理解为 a 是阶乘函数,而 b 是实际的参数。

<factorial> = lambda a, b: b*a(a, b-1) if b > 0 else 1

这一部分是阶乘的应用:

<factorial-application> = (lambda a, b: a(a, b))(<factorial>, b)

a 就是阶乘函数本身。它把自己作为第一个参数,把计算的点作为第二个参数。只要你不介意用 a(a, b - 1) 来代替 a(b - 1),这可以推广到 recursive_lambda

recursive_lambda = (lambda func: lambda *args: func(func, *args))
print(recursive_lambda(lambda self, x: x * self(self, x - 1) if x > 0 else 1)(6))
# Or, using the function verbatim:
print(recursive_lambda(lambda a, b: b*a(a, b-1) if b > 0 else 1)(6))

所以我们有外部部分:

(lambda b: <factorial-application>)(num)

如你所见,调用者只需要传入计算的点。


如果你真的想要一个递归的 lambda,你可以给这个 lambda 起个名字,来实现自我调用:

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

如果不想这样,你可以使用一个简单的辅助函数。你会注意到 ret 是一个可以自我引用的 lambda,这和之前的代码不同,之前的 lambda 不能自我引用。

def recursive_lambda(func):
    def ret(*args):
        return func(ret, *args)
    return ret

print(recursive_lambda(lambda factorial, x: x * factorial(x - 1) if x > 1 else 1)(6))  # 720

无论哪种方式,你都不需要用奇怪的方法让 lambda 自我调用。

撰写回答