Python迭代器的奇怪行为 [英] Weird behavior of Python iterator

查看:116
本文介绍了Python迭代器的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在玩Python生成器和 itertools 模块,并尝试制作Eratosthenes Sieve的无限版本。这是我的代码:

I was playing around with Python generators and the itertools module and tried making an infinite version of the Sieve of Eratosthenes. Here is my code:

from itertools import count, ifilter, islice

def sieve_broken():
    candidates = count(start=2)
    while True:
        prime = next(candidates)
        yield prime
        candidates = ifilter(lambda n: n % prime, candidates)

当我测试它时,我得到这个:

When I test it out, I get this:

>>> print list(islice(sieve_broken(), 10))
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

但如果我用这样的函数替换候选人的重新分配:

But if I replace the reassignment of candidates with a function like so:

def sieve_fixed():
    def exclude_multiples(factor, numbers):
        return ifilter(lambda n: n % factor, numbers)

    candidates = count(start=2)
    while True:
        prime = next(candidates)
        yield prime
        candidates = exclude_multiples(prime, candidates)

我得到:

>>> print list(islice(sieve_fixed(), 10))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

我无法弄清楚为什么第一个版本不起作用。据我所知,这两个版本应该是等价的。有谁知道为什么他们不一样?

I can't figure out why the first version doesn't work. As far as I can tell, the two versions should be equivalent. Does anyone know why they're not the same?

推荐答案

你已成为在Python中使用闭包时非常常见的陷阱:闭包随身携带它们的范围,你不断更换相同范围内的值。

You've fallen prey to a very common pitfall when using closures in Python: closures carry their scope, and you keep replacing the value in the same scope.

candidates = ifilter(lambda n, prime=prime: n % prime, candidates)

这篇关于Python迭代器的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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