小编典典

Python 2 vs Python 3-过滤器行为的差异

python

有人可以帮助我理解为什么以下实现“ Eratosthenes筛子”的代码在Python 2和Python 3中的行为会有所不同。

l = range(2, 20)
for i in range(2, 6):
    l = filter(lambda x: x == i or x % i != 0, l)
print(tuple(l))

使用Python 2.7:

> python filter.py
(2, 3, 5, 7, 11, 13, 17, 19)

使用Python 3.6:

> python filter.py
(2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 19)

我了解Python3的过滤器会返回过滤器对象,但无法解释最终结果。(代码来自此lambdas教程1)。


阅读 210

收藏
2021-01-20

共1个答案

小编典典

这里有两个部分起作用:

  • python-3.x中,它filter用作生成器:过滤是延迟完成的;和
  • ilambda x : ...更新,以及在ifor环,使进展。

因此,最后构建的内容类似于:

l = filter(lambda x: x == 5 or x % 5 != 0,
        filter(lambda x: x == 5 or x % 5 != 0,
            filter(lambda x: x == 5 or x % 5 != 0,
                filter(lambda x: x == 5 or x % 5 != 0,l)
            )
        )
    )

请注意,
所有过滤操作似乎i一直5都在进行。因此,现在您调用tuple(..),将完成实际的过滤,并且您将看到过滤出的不是五个主题的五个的倍数。

一个简单的解决方法是list在循环中使用,以便filter主动完成操作:

l = range(2, 20)
for i in range(2, 6):
    l = list(filter(lambda x: x == i or x % i != 0, l))
print(tuple(l))

在python中运行此命令会返回:

>>> l = range(2, 20)
>>> for i in range(2, 6):
...     l = list(filter(lambda x: x == i or x % i != 0, l))
... 
>>> print(l)
[2, 3, 5, 7, 11, 13, 17, 19]

请注意,尽管python-2.7python-3.x看起来完全一样,但它们实际上是互不兼容的“不同”语言:用一种语言编写的代码无法始终在另一种语言上运行,反之亦然。

另一个注意事项(贷记@ShadowRanger)是实际上 可以绑定i到您的lambda中。您可以通过创建“高阶lambda”来实现。而不是写:

lambda x : x == i or x % i != 0

你写:

(lambda j : (lambda x : x == j or x % j != 0))(i)

发生的事情是定义一个函数,该函数将aj实际取值为i。通过立即调用,j绑定到的值i

2021-01-20