Tri*_*max 6 python lambda python-2.x python-3.x
为什么这个代码
>>> i=1
>>> add_one=lambda x:x+i
>>> my_list=[add_one(i) for i in [0,1,2]]
Run Code Online (Sandbox Code Playgroud)
在Python 2.7中抛出此结果:
>>> my_list
[0, 2, 4]
Run Code Online (Sandbox Code Playgroud)
但是Python 3.3中的相同代码会抛出另一个结果:
>>> my_list
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
对我来说,Python 2.7的结果更有意义,因为'i'变量与调用lambda函数的名称范围相同.我不理解Python的两个分支中lambdas函数的这些不等行为.
Bre*_*arn 13
不同之处在于,在Python 3中,列表推导不会将其变量泄漏到封闭范围中.你可以在这里看到Guido对此的一些讨论; 该帖子包含一个非常类似于你的例子.
在这两个版本中,您add_one(i)都是一个引用变量的函数i.在调用函数时,将在封闭范围中按名称查找此变量.由于函数是在全局模块级别定义的,因此"封闭范围"是全局范围.这意味着当你调用add_one它时将使用i它在全局范围内找到的任何值(即,它将查找一个名为的全局变量i).
在Python 2中,列表推导将其变量泄漏i到封闭范围.由于列表推导位于全局模块级范围,因此"封闭范围"也是i全局变量,泄漏变量是全局变量,会覆盖您最初使用i = 1行设置的值.add_one然后调用引用此变量.由于i每次迭代都会发生变化,因此您的函数i+i在每次迭代时都会有效.
在Python 3中,列表推导在私有范围内创建自己的变量.但是你的功能仍然可以访问全局i.由于Python 3列表理解不会泄漏到全局范围,因此这个全局i永远不会改变,并且您的函数x+1在每次迭代时都会有效地执行(其中x是列表推导的循环变量).
| 归档时间: |
|
| 查看次数: |
1275 次 |
| 最近记录: |