从Python的Programming FAQ来看,这并不像许多人期望的那样有效:
>>> squares = []
>>> for x in range(5):
... squares.append(lambda: x**2)
>>> squares[2]() # outputs 16, not 4
提供以下解释:
This happens because
x
is not local to the lambdas, but is defined in the outer scope, and it is accessed when the lambda is called --- not when it is defined.
这很好。然而,对我来说,这个解释听起来并不完全正确。考虑这一点:
def buildFunction():
myNumber = 6 # Won't compile without this line
def fun():
return myNumber
return fun
def main():
myNumber = 3 # Ignored
myFun = buildFunction()
myNumber = 3 # Ignored
print(myFun()) # prints 6, not 3
这是有道理的,但是有人能提供一个更准确/通用的定义来说明何时发生Python闭包的变量绑定吗
每个变量都有一个作用域。 名称查找(获取名称指向的值)默认解析为最内部的范围。 只能重写本地作用域或包含作用域中的名称(使用关键字
nonlocal
和global
)。 在main中的第二个示例中,您将myNumber
分配给fun函数可以访问的不同范围调用
fun
时,Python查看fun
的局部作用域,但找不到myNumber
。 所以它查看它的包含范围。buildFunction
作用域在作用域(myNumber = 6
)中有myNumber
,因此fun
返回6
如果
buildFunction
在作用域中没有myNumber
,那么Python将查看下一个作用域。 在我的版本中,全局作用域有myNumber = 1
所以fun
将返回1
如果
myNumber
在全局作用域中也不存在,则会引发NameError
,因为在本地作用域或其任何包含作用域中都找不到myNumber
考虑如下:
这与lambda示例更具可比性,因为闭包函数嵌套在声明感兴趣变量的范围内。您的示例有两个不同的作用域,因此有两个完全不相关的
myNumbers
如果您没有遇到
nonlocal
关键字,您能猜出这将打印什么吗相关问题 更多 >
编程相关推荐