一个常规函数在其定义中可以包含对自身的调用,这没有问题。但是我无法想象如何使用lambda函数实现这一点,因为lambda函数没有名称可以引用回来。有没有办法做到这一点?怎么做呢?
一个常规函数在其定义中可以包含对自身的调用,这没有问题。但是我无法想象如何使用lambda函数实现这一点,因为lambda函数没有名称可以引用回来。有没有办法做到这一点?怎么做呢?
我能想到的唯一方法就是给这个函数起一个名字:
fact = lambda x: 1 if x == 0 else x * fact(x-1)
或者,对于较早版本的Python:
fact = lambda x: x == 0 and 1 or x * fact(x-1)
更新: 根据其他答案的思路,我成功地将阶乘函数嵌入单个无名lambda函数中:
>>> map(lambda n: (lambda f, *a: f(f, *a))(lambda rec, n: 1 if n == 0 else n*rec(rec, n-1), n), range(10))
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
这是可能的,但并不是真正推荐的做法!
map(lambda n: (lambda f, n: f(f, n))(lambda f, n: n*f(f, n-1) if n > 0 else 1, n), range(10))
- jfsfibonacci = lambda n: 0 if n == 0 else 1 if n == 1 else fibonacci(n-1)+fibonacci(n-2)
。 - martineauf = lambda x: 1 if x in (1,2) else f(x-1)+f(x-2)
- Juan Gallostra不使用reduce、map、命名lambda或Python内部函数:
(lambda a:lambda v:a(a,v))(lambda s,x:1 if x==0 else x*s(s,x-1))(10)
a = lambda myself, x: 1 if x==0 else x * myself(myself, x-1)
,然后是 v = 10
,最后是 a(a, v)
。这个复杂的 lambda 函数被设计为接受自身作为第一个参数(因此我将参数重命名为 myself
),它使用这个参数来递归调用自己。 - Felipe:=
,它给出了(f:=lambda x: 1 if x == 0 else x*f(x - 1))(5)
,这样更短更易读。 - gruvw与某些人所说的相反,您可以直接执行此操作。
(lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))(n)
首先介绍一个与lambda演算中递归有关的不动点组合子,它被称为Y组合子。
Y = (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))
第二部分是阶乘函数fact的递归定义。
fact = (lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))
F = Y(fact)
这个应用于第三部分n,其表示为n的阶乘。
>>> n = 5
>>> F(n)
120
或等价地
>>> (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))(5)
120
如果你更喜欢说谎而不是事实,你也可以使用相同的组合器
>>> (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: f(i - 1) + f(i - 2) if i > 1 else 1))(5)
8
:=
,它给出了 (f:=lambda x: 1 if x == 0 else x*f(x - 1))(5)
,这个更短更易读。 - gruvw你不能直接这样做,因为它没有名字。但是有一个像Lemmy指向的Y组合子帮助函数,你可以通过将函数作为参数传递给自身来创建递归(尽管听起来很奇怪):
# helper function
def recursive(f, *p, **kw):
return f(f, *p, **kw)
def fib(n):
# The rec parameter will be the lambda function itself
return recursive((lambda rec, n: rec(rec, n-1) + rec(rec, n-2) if n>1 else 1), n)
# using map since we already started to do black functional programming magic
print map(fib, range(10))
这段代码打印出前十个斐波那契数列的数字:[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
。
是的,我有两种方法来做到这一点,其中一种已经被涵盖了。这是我的首选方式。
(lambda v: (lambda n: n * __import__('types').FunctionType(
__import__('inspect').stack()[0][0].f_code,
dict(__import__=__import__, dict=dict)
)(n - 1) if n > 1 else 1)(v))(5)
>>> (lambda f: f(f))(lambda f, i=0: (i < 10)and f(f, i + 1)or i)
10
>>>
(lambda a:lambda v:a(a,v))(lambda s,x:1 if x==0 else x*s(s,x-1))(10)
>>> (f:=lambda x: 1 if x <= 1 else f(x - 1) + f(x - 2))(5)
8
阶乘:
>>> (f:=lambda x: 1 if x == 0 else x*f(x - 1))(5)
120
:=
来命名lambda函数:在lambda函数内直接使用名称,并立即调用它作为匿名函数。def recursive(def_fun):
def wrapper(*p, **kw):
fi = lambda *p, **kw: def_fun(fi, *p, **kw)
return def_fun(fi, *p, **kw)
return wrapper
factorial = recursive(lambda f, n: 1 if n < 2 else n * f(n - 1))
print(factorial(10))
fibonaci = recursive(lambda f, n: f(n - 1) + f(n - 2) if n > 1 else 1)
print(fibonaci(10))
希望对某些人有所帮助。
顺便说一下,与其进行缓慢的斐波那契计算:
f = lambda x: 1 if x in (1,2) else f(x-1)+f(x-2)
我建议对Fibonacci数列进行快速计算:
fib = lambda n, pp=1, pn=1, c=1: pp if c > n else fib(n, pn, pn+pp, c+1)
它的工作速度非常快。
还有阶乘计算:
fact = lambda n, p=1, c=1: p if c > n else fact(n, p*c, c+1)
简短回答
Z = lambda f : (lambda x : f(lambda v : x(x)(v)))(lambda x : f(lambda v : x(x)(v)))
fact = Z(lambda f : lambda n : 1 if n == 0 else n * f(n - 1))
print(fact(5))
编辑日期:2022年04月24日
说明
对于这个问题,我们可以使用不动点组合子,特别是Z
组合子,因为它适用于严格语言,也称为急切语言:
const Z = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)))
定义fact
函数并对其进行修改:
1. const fact n = n === 0 ? 1 : n * fact(n - 1)
2. const fact = n => n === 0 ? 1 : n * fact(n - 1)
3. const _fact = (fact => n => n === 0 ? 1 : n * fact(n - 1))
请注意:
fact === Z(_fact)
并使用它:
const Z = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)));
const _fact = f => n => n === 0 ? 1 : n * f(n - 1);
const fact = Z(_fact);
console.log(fact(5)); //120
reduce(f, (a,b,c,d))
表示f(f(f(a, b), c), d)
。 - jfs