循环变量泄露与延迟绑定叠加在一起,会产生一些让人迷惑的结果。

先看看一开始的问题,可以看到这里lambda函数的返回值一直在变。

由于Python没有块级作用域,所以循环会改变当前作用域变量的值,也就是循环变量泄露。

注意:Python3中列表推导式循环变量不会泄露,Python2中和常规循环一样泄露。

再讲一下闭包,在一个内部函数中,对外部作用域的变量进行引用,(并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包。

这里所谓的引用可以也就是内部函数记住了变量的名称(而不是值,这个从ast语法树可以看出),而变量对应的值是会变化的。

如果在循环中定义闭包,引用的变量的值在循环结束才统一确定为最后一次循环时的值,也就是延迟绑定(lazy binding)。

所以下面的例子,xx的所有匿名函数的返回值均为3

再分析一开始的问题,这里的匿名函数引用了变量i,而i是全局变量,所以再次使用i作为循环变量时,列表中的匿名函数引用的值就被覆盖了。