默认参数和currying:Python与Javascrip

2024-04-29 04:01:52 发布

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

考虑以下问题:我想创建一个函数数组,每个函数只在该数组中打印其索引。在Python中,使用

funcs = []
for i in range(5):
   funcs.append(lambda i=i: print(i))
funcs[2]()
# 2

这里我们使用默认的参数值来进行curry(如果我理解正确的话)。在

在ES6之前,Javascript中没有默认的参数值,所以currying必须以不同的方式完成。现在我们有了它们,我试着把Python翻译成Javascript:

^{pr2}$

为什么会失败?Python和Javascript传递默认值的方式有什么区别?在

(好吧,我知道我可以在这里使用let,而不是{},我只是在用Python几年之后学习Javascript,并试图理解它。)


Tags: lambda函数infor方式range数组javascript
3条回答

Javascript和Python都在闭包中使用后期绑定。但是,使用默认参数是一种让您模拟Python中早期绑定的方法,这是因为在Python中,默认参数是在函数定义时计算的。但是,在Javascript默认参数中,根据文档

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters

The default argument gets evaluated at call time, so unlike e.g. in Python, a new object is created each time the function is called.

下面是Python中使用的一种解决方案,可以在Javascript中应用于这个问题。我已经尽我所能把它翻译成Javascript。本质上,定义另一个返回原始值的匿名函数,并同时应用它。这在我看来非常混乱,在Python中,我总是使用默认参数:

funcs = []
for (var i = 0; i < 5; i++) {
    funcs.push((function (i) {return function() {console.log(i)}})(i))
};
funcs[0]() // 0
funcs[4]() // 4

在Python中:

^{pr2}$

我认为很明显,您应该在Javascript中使用.bind,正如其他答案所述,而不是这个笨重的解决方案。在

在python和JavaScript中,当参数在闭包中被绑定时,默认值之间的差异。虽然JavaScript和Python都使用后期绑定,但在默认参数的情况下,Python模拟早期绑定,而JavaScript不模拟。在

这就是说,如果您要创建这样的闭包,那么您可以充分利用它们,诚实地将所有参数都抛弃掉。在

您提到了let的用法,如果您想在for循环中定义函数,这一点很重要,因为否则{}将始终是迭代器的最大值(由于JavaScript闭包的后期绑定)。在

试试这个:

funcs = []; for (let i=0; i<5; i++) { funcs.push(function () {console.log(i)}); } funcs[2]();

和13;
和13;

或者,如果您希望遵循不在循环中定义函数的良好实践,可以在外部定义函数,并使用.bind()传递变量。需要注意的是,此方法将在调用.bind()时将变量与值绑定,因此不必使用let

和13;

和13;

如果使用let而不是var,则每次迭代都会得到一个新的绑定。在

funcs = []
for (let i=0; i<5; i++) {
  funcs.push(function (j=i) {console.log(j)})
}

funcs[2];//2

i=i不起作用,因为在ES6中,参数可以使用其他参数定义默认值

^{pr2}$

所以解析器变得很混乱。在

相关问题 更多 >