用Python lambda函数计算数字的阶乘
我刚开始学习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 个回答
让我们像剥洋葱一样,把这行代码拆开来看看。
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
这有点让人困惑,因为它写成了一行很复杂的代码 :)
就是这么简单:
n=input()
print reduce(lambda x,y:x*y,range(1,n+1))
阶乘的概念基本上是你想象中的样子。你可以理解为 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 自我调用。