我刚开始学习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)是什么意思?
有人能解释一下吗?
谢谢
我刚开始学习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)是什么意思?
有人能解释一下吗?
谢谢
阶乘函数本身就像你预期的那样。你可以推断出 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传递给自身。
a
是被传递给它自己吗? - ApproachingDarknessFishn=input()
print reduce(lambda x,y:x*y,range(1,n+1))
让我们像剥洋葱一样分解这个一行代码。
print (lambda b: (Y))(num)
(lambda a, b: a(a, b))(X,b)
在 lambda 函数内部,我们定义了另一个 lambda 函数。将其称为 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
由于它被写成一行令人困惑的代码,所以可能会让人感到困惑 :)
fact = lambda n:1 if n==0 else n*fact(n-1)
print(fact(5)
>>> 120
这个函数有两个难点。
1. lambda a, b: b*a(a, b-1) if b > 0 else 1
。
2. 接在1后面的那个“b”。
对于第一个难点,它不过是:
def f(a, b):
if b > 0:
b * a(a, b - 1)
else:
1
对于2,这是b
(lambda b: (lambda a, b: a(a, b))(lambda a, b: b*a(a, b-1) if b > 0 else 1,b))(num)
(this one)
实际上是这样的 b:
(lambda b: (lambda a, b: a(a, b))(lambda a, b: b*a(a, b-1) if b > 0 else 1,b))(num)
(this one)
原因是它不在第二个和第三个lambda的定义内,所以它引用了第一个b。
在我们应用num并剥离外部函数之后:
(lambda a, b: a(a, b)) (lambda a, b: b*a(a, b-1) if b > 0 else 1, num)
这只是将函数应用到元组上,(lambda a, b: b*a(a, b-1) if b > 0 else 1, num)
我们将这个元组称为(f, num) (f的定义在上面)
将lambda a, b: a(a, b)
应用于它,我们得到
f(f, num).
假设你的num是5。
根据f的定义,它首先计算为
5 * f(f, 4)
然后转为:
5 * (4 * f(f, 3))
一直到底部
5 * (4 * (3 * (2 * (1 * f(f, 0)))))
f(f,0)的结果为1。
5 * (4 * (3 * (2 * (1 * 1))))
开始吧,5的阶乘。
递归lambda的一般定义如下:
recursive_lambda = (lambda func: lambda *args: func(func, *args))
使用Lambda函数查找阶乘的简单方法
fac = lambda x : x * fac(x-1) if x > 0 else 1
print(fac(5))
输出: 120
用户输入以查找阶乘
def fac():
fac_num = int(input("Enter Number to find Factorial "))
factorial = lambda f : f * factorial(f-1) if f > 0 else 1
print(factorial(fac_num))
fac()
输入要查找阶乘的数字:5
120
相关代码:
lambda b : (lambda a, b : a(a, b)) (lambda a, b : b * a(a, b-1) if b > 0 else 1, b)
f代替变量名a,用n代替变量名b
。lambda n : (lambda f, n : f(f, n)) (lambda f, n : n * f(f, n-1) if n > 0 else 1, n)
递归阶乘是一个会调用自身或应用于自身的函数,类似于 f(f)。
让我们将 Factorial(n) 设为 f(f,n)
并按以下方式计算:
def func(f, n): # takes a function and a number, return a number.
if n > 0 :
return n * f(f, n-1)
else :
return 1
将上述的def func函数转换为lambda表达式:
func is lambda f, n : n * f(f, n-1) if n > 0 else 1
接下来需要将函数应用于自身和整数n。
回到最初的语句,Factorial(n)是f(f,n),或者当将函数func应用于f时,为f(func,n)。
def Factorial(n):
# return f (func, n) # next, substitute f and func with their corresponding lambdas.
return (lambda f, n : f(f, n)) (lambda f, n : n * f(f, n-1) if n > 0 else 1, n)
使用lambda代替def阶乘,整个代码如下:
lambda n : (lambda f, n : f(f, n)) (lambda f, n : n * f(f, n-1) if n > 0 else 1, n)
if x==1:
return 1
else
return x*function_name(x-1)
例如,fact
是我的 lambda 表达式:
fact(lambda x: 1 if x == 1 else x * fact(x-1))
lambda b: math.factorial(b)
。 - JBernardo