列表解析中的Lambda在调用时返回Lambda [英] Lambdas from a list comprehension are returning a lambda when called

查看:54
本文介绍了列表解析中的Lambda在调用时返回Lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试像test.py中那样在列表上迭代lambda函数,并且我想获取lambda的调用结果,而不是函数对象本身.但是,以下输出确实使我感到困惑.

I am trying to iterate the lambda func over a list as in test.py, and I want to get the call result of the lambda, not the function object itself. However, the following output really confused me.

------test.py---------
#!/bin/env python
#coding: utf-8

a = [lambda: i for i in range(5)]
for i in a:
    print i()

--------output---------
<function <lambda> at 0x7f489e542e60>
<function <lambda> at 0x7f489e542ed8>
<function <lambda> at 0x7f489e542f50>
<function <lambda> at 0x7f489e54a050>
<function <lambda> at 0x7f489e54a0c8>

当按如下所示将调用结果打印到t时,我修改了变量名称,一切顺利.我想知道这是怎么回事. ?

I modified the variable name when print the call result to t as following, and everything goes well. I am wondering what is all about of that. ?

--------test.py(update)--------
a = [lambda: i for i in range(5)]
for t in a:
    print t()

-----------output-------------
4
4
4
4
4

推荐答案

在Python 2中,列表理解将变量泄漏"到外部范围:

In Python 2 list comprehension 'leaks' the variables to outer scope:

>>> [i for i in xrange(3)]
[0, 1, 2]
>>> i
2

请注意,Python 3上的行为不同:

Note that the behavior is different on Python 3:

>>> [i for i in range(3)]
[0, 1, 2]
>>> i
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'i' is not defined

定义lambda时,它绑定到变量i,而不是第二个示例所示的当前值. 现在,当您为i分配新值时,lambda将返回当前值:

When you define lambda it's bound to variable i, not its' current value as your second example shows. Now when you assign new value to i the lambda will return whatever is the current value:

>>> a = [lambda: i for i in range(5)]
>>> a[0]()
4
>>> i = 'foobar'
>>> a[0]()
'foobar'

由于循环中i的值是lambda本身,您将获得它作为返回值:

Since the value of i within the loop is the lambda itself you'll get it as a return value:

>>> i = a[0]
>>> i()
<function <lambda> at 0x01D689F0>
>>> i()()()()
<function <lambda> at 0x01D689F0>

更新:Python 2.7上的示例:

UPDATE: Example on Python 2.7:

Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [lambda: i for i in range(5)]
>>> for i in a:
...     print i()
... 
<function <lambda> at 0x7f1eae7f15f0>
<function <lambda> at 0x7f1eae7f1668>
<function <lambda> at 0x7f1eae7f16e0>
<function <lambda> at 0x7f1eae7f1758>
<function <lambda> at 0x7f1eae7f17d0>

与Python 3.4相同:

Same on Python 3.4:

Python 3.4.3 (default, Oct 14 2015, 20:28:29) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [lambda: i for i in range(5)]
>>> for i in a:
...     print(i())
... 
4
4
4
4
4

有关通过列表理解进行变量范围更改的详细信息,请参见Guido的 2010年以来的博客.

For details about the change regarding the variable scope with list comprehension see Guido's blogpost from 2010.

我们还对Python 3进行了另一处更改,以改善列表理解与生成器表达式之间的等效性.在Python 2中,列表理解将循环"控制变量泄漏"到周围的作用域中:

We also made another change in Python 3, to improve equivalence between list comprehensions and generator expressions. In Python 2, the list comprehension "leaks" the loop control variable into the surrounding scope:

x = 'before'
a = [x for x in 1, 2, 3]
print x # this prints '3', not 'before'

但是,在Python 3中,我们决定通过使用与生成器表达式相同的实现策略来修复列表理解的肮脏的小秘密".因此,在Python 3中,上述示例(在修改为使用print(x):-之后)将打印"before",证明列表理解中的"x"会暂时遮盖阴影,但不会覆盖周围的"x"范围.

However, in Python 3, we decided to fix the "dirty little secret" of list comprehensions by using the same implementation strategy as for generator expressions. Thus, in Python 3, the above example (after modification to use print(x) :-) will print 'before', proving that the 'x' in the list comprehension temporarily shadows but does not override the 'x' in the surrounding scope.

这篇关于列表解析中的Lambda在调用时返回Lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆