I have just started learning python. I came across lambda functions. On one of the problems, the author asked to write a one liner lambda function for factorial of a number.
Very nicely explained! Only one minor fix: if b > 1 NOT if b > 0
The result is the same but logically more correct as it is executing one unnecessary additional loop (even though multiplying by 1)
Wikipedia => n!, is the product of all positive integers less than or equal to n
while True:
#It is this simple:
from functools import reduce
n=input('>>')
n=int(n)
if n==0:
print('factorial: ',1)
elif n<0:
print('invalid input')
else:
print('factorial: ',(reduce(lambda x,y:x*y,list(range(1,n+1)))))
Let's peel this one liner open like an onion.
print (lambda b: (Y))(num)
We are making an anonymous function (the keyword lambda means we're about to type a series of parameter names, then a colon, then a function that uses those parameters) and then pass it num to satisfy its one parameter.
(lambda a, b: a(a, b))(X,b)
Inside of the lambda, we define another lambda. Call this lambda Y. This one takes two parameters, a and b. a is called with a and b, so a is a callable that takes itself and one other parameter
(lambda a, b: b*a(a, b-1) if b > 0 else 1
,
b)
These are the parameters to Y. The first one is a lambda function, call it X. We can see that X is the factorial function, and that the second parameter will become its number.
That is, if we go up and look at Y, we can see that we will call:
X(X, b)
which will do
b*X(X, b-1) if b > 0 else 1
and call itself, forming the recursive part of factorial.
And looking all the way back outside, we can see that b is num that we passed into the outermost lambda.
num*X(X, b-1) if num > 0 else 1
This is kind of confusing because it was written as a confusing one liner :)
Easy Method to find Factorial using Lambda Function
fac = lambda x : x * fac(x-1) if x > 0 else 1
print(fac(5))
output: 120
User Input to find Factorial
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()
Enter Number to find Factorial : 5
120
The code in question:
lambda b : (lambda a, b : a(a, b)) (lambda a, b : b * a(a, b-1) if b > 0 else 1, b)
To make it clearer, let me replace variable names a with f, and b with n
.
lambda n : (lambda f, n : f(f, n)) (lambda f, n : n * f(f, n-1) if n > 0 else 1, n)
Recursive Factorial is a function that will call itself, or be applied to itself, something like f(f).
Let us set Factorial(n) to be f(f,n)
and compute as follows:
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
Translating the above def func into lambda notation:
func is lambda f, n : n * f(f, n-1) if n > 0 else 1
func is then to be applied to itself along with integer n.
Back to beginning statement, Factorial(n) is f(f,n), or f(func,n) when func is applied into f.
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)
and using lambda instead of def Factorial, the whole thing becomes:
lambda n : (lambda f, n : f(f, n)) (lambda f, n : n * f(f, n-1) if n > 0 else 1, n)