2015-10-17 56 views
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]。为什么?

它是否与在迭代它的循环内执行序列时期望的麻烦有关?

谢谢你的任何提示。

回答

2

您的问题是由发电机表达提到的pr相同pr您修改在while循环的下一个迭代,所以每数由之前的“黄金”号的处理,这些是不能分开的作为'总理'。它本身修改pr等。在excl函数中,您引用的pr是作为参数传递的参数,它永远不会更改。

+0

我不确定我是否理解这个答案。素数不会在excl(也不在gen.expression)中改变,它在循环内发生变化,并且此内容对于内联和“调用”版本而言是相同的。顺便说一句,我删除了关于filter()的错误评论。 –

+0

@JerzyKarczmarczuk根据[PEP 227](https://www.python.org/dev/peps/pep-0227/),如果在代码块(嵌套函数)中使用名称,但它不在那里绑定并且未声明为全局函数,则将该用法视为对最近的函数区域的引用。由于它适用于你的情况,生成器表达式是引擎盖下的一个函数,它不定义变量'pr',因此它的'pr'是封闭函数中的'pr'的**引用**( 'sieve')。这意味着当'sieve'中的'pr'改变时,发生器表达式中的'pr'也会改变。 – ppperry

相关问题