下面的闭包函数在javascript中可以正常工作。在
function generateNextNumber(startNumber) {
var current = startNumber;
return function(){
return current += 1;
}
}
var getNextNumber = generateNextNumber(10);
for (var i = 0; i < 10; i++) {
console.log(getNextNumber());
}
我试着用Python做同样的事情
^{pr2}$我得到以下错误
Traceback (most recent call last):
File "/home/thefourtheye/Desktop/Test1.py", line 10, in <module>
print (getNextNumber())
File "/home/thefourtheye/Desktop/Test1.py", line 4, in tempFunction
current += 1
UnboundLocalError: local variable 'current' referenced before assignment
当我在tempFunction
内打印vars()
和{
({'current': 10}, {'current': 10})
但当我把程序修改成这样
def generateNextNumber(startNumber):
current = {"Number" : startNumber}
def tempFunction():
current["Number"] += 1
return current["Number"]
return tempFunction
它起作用了。我无法解释为什么这会起作用。谁能解释一下吗?在
Python通过定义函数包含赋值的任何变量都是局部变量来决定函数的局部变量,除非声明了}。因此
nonlocal
或{创建一个名为
^{pr2}$current
的局部变量,该变量隐藏非局部变量。如果您使用的是python2,标准的解决方案(除了尽量不这样做之外)是将current
变成一个1元素列表并使用作为参考,“尝试不这样做”可能看起来像下面这样:
Python假设函数中的所有变量都是局部变量。这是为了避免意外使用同名的全局变量,或在封闭范围内使用。在某些重要的方面,这种差异是由于在Python中局部变量声明是自动/隐式的,而在JavaScript中则不是(必须使用
var
)。解决方案:使用
global
声明在某些情况下有效,但在您的实例中,
tempFunction
只能同时处于活动状态。在使用函数属性
^{pr2}$使用这样一个事实:函数是对象(因此可以具有属性),它们在声明时被实例化,并且它们成为封闭函数(或模块,在这种情况下,它们实际上是全局的)的局部的。这也是因为名称
tempFunction
是第一次在它自己的定义中使用“member access”.
运算符,因此没有假定为本地名称。“call”()
和“element access”[]
运算符也会发生类似的情况。后一个例子解释了代码为什么工作。在强制将名称假定为非本地
这已经在上一节中解释过了。通过使用成员访问操作符
.
,我们说“current
已经存在”,因此在封闭范围内搜索它。在这个特定的例子中,我们使用type
函数创建一个类,并立即创建它的一个实例(使用第二组parathese)。我们也可以使用列表或字典来代替一般对象。第二种情况是非常常见的解决办法。在使用函数对象
任何类具有调用方法的对象都是函数,因此可以用函数调用运算符
()
来调用。这与前两起案件极为相关。在使用
nonlocal
声明以同样的方式,
global
意味着。。。嗯,global,nonlocal
的意思是“在前一个范围内”。在Python3和Python2的更高版本中有效。在使用发电机
这可能是解决非局部变量访问的一般问题的最“python”方法,而是您用来解释它的特定情况。我不能不提一下就结束了。不过,你需要稍微改变一下:
当驱动
for
时,对next()
的调用是隐式的(但是生成器不能像我的示例中那样是无限的)。在相关问题 更多 >
编程相关推荐