gpt4 book ai didi

python - 列表推导中的 Lambda 在调用时返回一个 lambda

转载 作者:IT老高 更新时间:2023-10-28 20:27:40 24 4
gpt4 key购买 nike

我正在尝试在 test.py 中的列表上迭代 lambda func,并且我想获取 lambda 的调用结果,而不是函数对象本身。但是,下面的输出真的让我很困惑。

------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时修改了变量名,如下所示,一切顺利。我想知道这是怎么回事。 ?

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

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

这种行为是 2.x 特有的,是 What do lambda function closures capture? 中描述的问题的一个特例。 .在 3.x 中,列表推导为迭代变量创建了自己的范围,因此它不能从外部修改。然而,它仍然是后期绑定(bind),所以每个print都会产生4

最佳答案

在 Python 2 中,列表解析将变量“泄漏”到外部范围:

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

请注意,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 时,它绑定(bind)到变量 i,而不是第二个示例所示的当前值。现在,当您为 i 分配新值时,lambda 将返回当前值:

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

由于循环中 i 的值是 lambda 本身,因此您将其作为返回值:

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

更新: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 上也是如此:

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 的 blogpost from 2010 .

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'

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.

关于python - 列表推导中的 Lambda 在调用时返回一个 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38369470/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com