考虑这个(相当无意义)的JavaScript代码:
function make_closure() {
var x = 123, y = 456;
return function(varname) { return eval(varname) }
}
closure = make_closure()
closure("x") // 123
closure("y") // 456
从返回的功能make_closure
不包含范围变量的任何引用,但仍然能够调用时返回它们的值。
有没有办法做同样的蟒蛇?
def make_closure():
x = 123
return lambda varname: ...no "x" here...
closure = make_closure()
print closure("x") # 123
换句话说,如何写关闭,将“知道”定义范围没有明确提到他们的变量?
这可能是最接近完全等效:
def make_closure():
x = 123
l = locals()
return lambda(varname): eval(varname, None, l)
closure = make_closure()
print closure("x") # 123
最终,你的问题不在于X不是由当地的封闭拍摄,但当地的范围并没有传递到EVAL。
见http://docs.python.org/library/functions.html#eval有关eval函数的详细信息。
它可能不用说,这是不是做了非常Python化的事情。 你几乎从来没有真正想调用EVAL在Python; 如果你认为你这样做,退一步,重新审视自己的更大的设计。 但是,当你需要使用它,你需要了解它是如何从Javascript的eval不同。 它的最终功能更强大,它可以被用来模拟动态作用域,或作为EXEC的简化版本,或以任何任意构造的评估代码环境,但是这也意味着它是棘手。
利用人们已经提到locals()
另外,诚然不太灵活,方法是使用新的nonlocal
关键词在Python 3:
>>> def make_closure():
... x = 123
... def return_var(varname):
... nonlocal x
... return eval(varname)
... return return_var
...
>>> closure = make_closure()
>>> closure("x")
123
这有需要你明确地标注来自外部范围,你要关闭了,并引用变量的明显缺点。
您可以紧密围绕变量在Python中,大约你如何在Javascript将:
def foo():
x = 123
return lambda y: x+y
q = foo()
print q(5)
http://ideone.com/Q8iBg
不过,也有一定的差异 - 例如,你可以不写在父母的范围变量(试图只写创建一个局部范围的变量来代替)。 此外,Python的eval()
不包括父范围。
您可以绕过此为eval()
通过明确从父范围抓住了当地人并将它们传递到孩子eval()
作为它的当地人的说法,但这里真正的问题是,为什么你要这么做?
在Python 2.x的,这需要一些大规模kludging。 然而,在Python 3.X的“外地”的关键字被引入到允许访问的变量直接封闭范围。
这可能是值得检查这里了解更多信息: 在Python 2.x的外地关键字