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

相關問題