有趣的递归lambda examp

2024-04-19 21:20:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我只是偶然发现了一个递归lambdas的有趣例子,我真的不明白它为什么以这种方式工作。你知道吗

rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec 
rec = lambda x: x+1
print(f(10))  

在javascript中也是如此。你知道吗

var rec = function(a) { if (a == 0) return 1; return rec(a - 1) * a; } var f = rec rec = function(a) { return a + 1; } console.log(f(10));

令我惊讶的是,这两张照片都是100张而不是10张!(如我所料)。你知道吗

为什么rec的重新分配会改变f函数的行为?在lambda中捕获rec变量时,它不是指lambda本身吗?你知道吗


编辑。 由于大多数答案解释了发生了什么,让我重新措辞的问题,因为我正在寻找一个更深入的解释。你知道吗

那么在第一行声明函数rec的时候,为什么函数体中的rec没有绑定到它自己呢?你知道吗

例如,如果您使用JavaScript并以一种看似“相同”的方式重写第一行,您将得到以下答案之一: 你知道吗

var rec =function rec(a) {
    if (a == 0) return 1;
    return rec(a - 1) * a;
};
f = rec;

rec = function (a) {
    return a + 1;
}

console.log(f(10));

这张打印出10张!正如人们所料。你知道吗

因此在本例中,“内部rec”(在函数体中)绑定到函数名的rec,而不是查看rec变量,并且变量rec的重新分配并没有改变行为。你知道吗

因此,我真正要问的是,这些语言决定如何绑定lambdas中的变量的机制。你知道吗

我正在为一个类项目编写一个解释器,我遇到了一个相同的问题,即何时何地绑定这些变量。所以我想了解如何在流行语言中实现类似的功能。你知道吗


Tags: lambda函数答案log语言returnifvar
3条回答

您可以添加一些console.log并查看,首先用10调用f,然后用9调用rec,结果是10 * 10。你知道吗

var rec = function(a) { console.log('f', a); if (a == 0) return 1; return rec(a - 1) * a; }; f = rec; rec = function(a) { console.log('rec', a); return a + 1; } console.log(f(10));

保持rec。你知道吗

我将为python解决这个问题,因为这是我所熟悉的。你知道吗

首先,这种行为是可能的,因为python(我想看起来像javascript)遵循闭包的后期绑定。further read

后期绑定是在运行时查找闭包中的名称(与早期绑定不同,早期绑定是在编译时查找名称)

这允许在运行时改变行为,通过重新绑定运行时正在查找的变量(例如rec之类的函数)。你知道吗

最后一步就是将lambda函数转换成等价的def语法,这样真正的行为就更清楚了。你知道吗

代码:

rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec 
rec = lambda x: x+1
print(f(10)) 

可等同于:

首先:

def somefunc(x):
    return 1 if x==0 else rec(x-1)*x 

注意,python不会抱怨rec即使在干净的会话/内核上也不存在,因为它在函数定义期间不查找该值。延迟绑定意味着除非调用这个函数,否则python不关心rec是什么。你知道吗

然后:

rec = somefunc
f = rec

def someotherfunc(x):
    return x + 1

f(10) #3628800

现在我们更改rec函数

rec = someotherfunc

并观察到f的后续函数调用将使用后期绑定rec,即在函数调用上查找的rec。你知道吗

f(10) #100

注:完整代码添加如下:

def somefunc(x):
    return 1 if x==0 else rec(x-1)*x

rec = somefunc

f = rec

def someotherfunc(x):
    return x + 1

f(10) #3628800

rec = someotherfunc

f(10) #100

这3条语句可以归结为一条语句

rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec 
rec = lambda x: x+1

从1&2

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

从上方&;3

f = lambda x : 1 if x==0 else x*x

相关问题 更多 >