[英]Troublesome filter behavior when implementing the “Sieve of Eratosthenes” in python
I came up with this Python code for the trial division variant of the "Sieve of Eratosthenes" : 我想出了“Eratosthenes筛选”的试验版变体的Python代码:
import itertools
def sieve():
# begin with all natural numbers above 1
picker = itertools.count(2)
while True:
# take the next available number
v = next(picker)
yield v
# filter from the generator its multiples
picker = filter(lambda x: x % v != 0, picker)
It doesn't work as I expected. 它没有像我预期的那样工作。
When debugging it I get some behavior I don't understand when filter
gets called: the x
parameter of the lambda gets a concrete argument which is the next element from the picker
generator. 在调试它时,我得到了一些在调用
filter
时我不明白的行为:lambda的x
参数得到一个具体的参数,它是picker
生成器的下一个元素。 I don't understand this behavior not even after looking at the documentation of filter
. 在查看
filter
的文档后,我不明白这种行为。
Running 运行
s = sieve()
for i in range(5):
print(next(s))
I get: 我明白了:
2
3
4
5
6
Instead of 代替
2
3
5
7
11
UPDATE: 更新:
My bug comes from a misunderstanding of how lambdas work in Python, more on that here . 我的错误来自于对lambdas如何在Python中工作的误解,更多关于这一点 。
Adding an extra parameter to the lambda fixes the issue: 向lambda添加额外的参数可以解决问题:
picker = filter(lambda x, prime = v: x % prime != 0, picker)
I think the problem is because you rely on local variables and the generators you create (using filter()
) are referencing the local variables which are overwritten when the generator goes on iterating. 我认为问题是因为你依赖局部变量而你创建的生成器(使用
filter()
)引用了当生成器继续迭代时被覆盖的局部变量。
If you use a local function instead, it works fine: 如果您使用本地函数,它可以正常工作:
def sieve():
def selector(iterator, d):
for x in iterator:
if x % d != 0:
yield x
picker = itertools.count(2)
while True:
# take the next available number
prime = next(picker)
yield prime
# filter from the generator its multiples
picker = selector(picker, prime)
Trying list(itertools.islice(sieve(), 10))
shows: 试用
list(itertools.islice(sieve(), 10))
显示:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
But I really need to point out that this is a purely educational solution to show how things work. 但我真的需要指出,这是一个纯粹的教育解决方案,以显示事情是如何运作的。 I would not propose to use this solution for any productive code.
我不建议将此解决方案用于任何生产性代码。 It builds up a large amount of generators internally which are freed only when you drop the handle of the parent generator.
它在内部构建了大量的生成器,只有在删除父生成器的句柄时才会释放它们。 This is probably a waste of resources and you can create an infinite amount of prime numbers without creating an infinite amount of generators.
这可能是浪费资源,您可以创建无限量的素数而无需创建无限量的生成器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.