Python生成器;两个明显相同的程序工作方式不同

Python生成器;两个明显相同的程序工作方式不同,python,generator,sieve,Python,Generator,Sieve,下面的程序[Python 3.4]是一个简单的Eratosthenes筛: from itertools import * def excl(ns,pr): return (i for i in ns if i%pr) def sieve(ns): while True: pr=next(ns) yield pr ns=excl(ns,pr) # ns=(i for i in ns if i%pr) r=list(i

下面的程序[Python 3.4]是一个简单的Eratosthenes筛:

from itertools import *
def excl(ns,pr):
    return (i for i in ns if i%pr)
def sieve(ns):
    while True:
        pr=next(ns)
        yield pr
        ns=excl(ns,pr)
        # ns=(i for i in ns if i%pr)
r=list(islice(sieve(count(2)),10))
产生[2,3,5,7,11,13,17,19,23,29]。好啊取消对包含excl()的行的注释,并对调用进行注释,将得到[2,3,4,5,6,7,8,9,10,11]。为什么?

它是否与在循环中修改序列时预期的故障有关


谢谢您的提示。

您的问题是生成器表达式引用的
pr
与您在while循环的下一次迭代中修改的相同,因此每个不能被前一个“素数”整除的数都被视为“素数”。它本身会修改
pr
,以此类推。在
excl
函数中,您引用的
pr
是作为参数传递的,它永远不会改变。

我不确定是否理解这个答案。prime pr在excl中(在gen.expression中也不改变),它在循环中改变,内联和“call”版本的上下文是相同的。顺便说一句,我删除了一条关于filter()的错误注释。@JerzyKarczmarczuk根据,如果在代码块(嵌套函数)中使用了一个名称,但它没有绑定在那里,也没有声明为全局的,则该使用将被视为对最近的封闭函数区域的引用。由于它适用于您的情况,生成器表达式是一个隐藏的函数,它没有定义变量
pr
,因此它的
pr
是对封闭函数(
sieve
)中的
pr
的引用。这意味着当
sieve
中的
pr
改变时,生成器表达式中的
pr
也会改变。