the*_*eye 14 javascript python closures
以下闭包函数在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());
}
Run Code Online (Sandbox Code Playgroud)
我试图用Python做同样的事情
def generateNextNumber(startNumber):
current = startNumber
def tempFunction():
current += 1
return current
return tempFunction
getNextNumber = generateNextNumber(10)
for i in range(10):
print (getNextNumber())
Run Code Online (Sandbox Code Playgroud)
我收到以下错误
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
Run Code Online (Sandbox Code Playgroud)
当我打印vars()和locals()内部tempFunction,他们证实current存在.
({'current': 10}, {'current': 10})
Run Code Online (Sandbox Code Playgroud)
但是当我修改程序时有点像这样
def generateNextNumber(startNumber):
current = {"Number" : startNumber}
def tempFunction():
current["Number"] += 1
return current["Number"]
return tempFunction
Run Code Online (Sandbox Code Playgroud)
有用.我无法解释为什么这样做.有人可以解释一下吗?
Mar*_*ssi 21
Python假定函数中的所有变量都是本地的.这是为了避免意外使用同名的全局变量或封闭的范围.在某些重要的方面,这种差异是因为在Python中局部变量声明是自动/隐式的,而在JavaScript中则不是(你必须使用var).解决方案:
global声明def generateNextNumber(startNumber):
global current
current= startNumber
def tempFunction():
global current
current += 1
return current
return tempFunction
Run Code Online (Sandbox Code Playgroud)
在某些情况下有效,但在您的情况下,只有一个实例tempFunction可以同时处于活动状态.
def generateNextNumber(startNumber):
def tempFunction():
tempFunction.current += 1
return tempFunction.current
tempFunction.current= startNumber
return tempFunction
Run Code Online (Sandbox Code Playgroud)
使用函数是对象(因此可以具有属性)的事实,它们在声明时被实例化,并且它们变为封闭函数(或模块,在这种情况下它们实际上是全局的)的本地.这也有效,因为名称tempFunction在其自己的定义中第一次使用"成员访问" .运算符,因此不被假定为本地名称."call" ()和"element access" []运算符会发生类似的情况.后一种情况解释了为什么您的代码有效.
def generateNextNumber(startNumber):
current= type("OnTheFly",(),{})()
current.value= startNumber
def tempFunction():
current.value += 1
return current.value
return tempFunction
Run Code Online (Sandbox Code Playgroud)
这已在前一节中解释过.通过使用成员访问运算符,.我们说" current已经存在",因此它在封闭范围内进行搜索.在这种特殊情况下,我们使用该type函数创建一个类并立即创建它的实例(使用第二组parantheses).我们也可以使用列表或字典而不是一般对象.第二种情况是一种非常普遍的解决方案.
def generateNextNumber(startNumber):
class TempFunction:
def __call__(self):
self.current += 1
return self.current
tempFunction= TempFunction()
tempFunction.current= startNumber
return tempFunction
Run Code Online (Sandbox Code Playgroud)
类具有call方法的任何对象都是函数,因此可以使用函数调用运算符调用().这与前两个案例极为相关.
nonlocal声明def generateNextNumber(startNumber):
current= startNumber
def tempFunction():
nonlocal current
current += 1
return current
return tempFunction
Run Code Online (Sandbox Code Playgroud)
同样global意味着......好吧,全球,nonlocal意味着"在前一个范围内".在Python 3和Python 2的更高版本中有效.
def generateNextNumber(current):
while True :
current+= 1
yield current
Run Code Online (Sandbox Code Playgroud)
这可能是最接近非本地变量访问的一般问题的"Pythonic"方法,但是您用来解释它的具体情况.没有提到它我无法完成.但是,您需要通过一个小改动来调用它:
getNextNumber = generateNextNumber(10)
for i in range(10):
print (getNextNumber.next())
Run Code Online (Sandbox Code Playgroud)
当驱动for调用next()是隐式的(但是生成器不能像我的例子那样是无限的).
| 归档时间: |
|
| 查看次数: |
2974 次 |
| 最近记录: |