6
下面[Python的3.4]是一个简单的埃拉托塞尼筛的程序:Python生成器;两个明显相同的程序的工作方式不同
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]。为什么?
它是否与在迭代它的循环内执行序列时期望的麻烦有关?
谢谢你的任何提示。
我不确定我是否理解这个答案。素数不会在excl(也不在gen.expression)中改变,它在循环内发生变化,并且此内容对于内联和“调用”版本而言是相同的。顺便说一句,我删除了关于filter()的错误评论。 –
@JerzyKarczmarczuk根据[PEP 227](https://www.python.org/dev/peps/pep-0227/),如果在代码块(嵌套函数)中使用名称,但它不在那里绑定并且未声明为全局函数,则将该用法视为对最近的函数区域的引用。由于它适用于你的情况,生成器表达式是引擎盖下的一个函数,它不定义变量'pr',因此它的'pr'是封闭函数中的'pr'的**引用**( 'sieve')。这意味着当'sieve'中的'pr'改变时,发生器表达式中的'pr'也会改变。 – ppperry