2014-10-05 28 views
4

我試圖讓下面的生成器能夠設置返回數字的上限。在Python中爲無限生成器設置限制

調用list(it.takewhile(lambda x: x < 100, get_primes()))收益100如預期,但list(get_primes(100))(應該以同樣的方式返回相同的列表)下的所有質數的列表只是一個空列表返回。

顯然,我可以在for循環中包含一個if n and candidate>=n: break,但我最感興趣的是爲什麼if n: return構造不能像我期待的那樣工作。它不應該只是返回上面工作的相同的takewhile迭代器嗎?我在這裏忽略了什麼?

import itertools as it 

def get_primes(n=None): 
    """ 
    Generates primes to a max of n. 

    >>> list(get_primes(100)) 
    [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] 
    """ 
    if n: 
     return it.takewhile(lambda x: x < n, get_primes()) 
    composites = {} 
    yield 2 
    for candidate in it.count(3, 2): 
     prime_factor = composites.pop(candidate, None) 
     if prime_factor is None: 
      yield candidate 
      composites[candidate**2] = candidate 
     else: 
      composite = candidate + 2*prime_factor 
      while composite in composites: 
       composite += 2*prime_factor 
      composites[composite] = prime_factor 

回答

3

這裏:

return it.takewhile(lambda x: x < n, get_primes()) 

由於這是一臺發電機,它需要yield這些值,而不是return荷蘭國際集團他們。根據您的Python版本,您可能可以使用yield from語法。

下可能會作爲背景閱讀有用:Return in generator together with yield in Python 3.3

+1

儘管用'yield'替換'return'並不會產生預期的行爲(生成器將產生另一個生成器作爲第一個值)。 – isedev 2014-10-05 19:44:17

+0

@isedev:'yield from'將直接替代'return'(一個普通的「yield」,當然不會)。 – NPE 2014-10-05 19:46:21

+0

當然,如果你可以使用從'yield'來商定。否則,實際的生成器將需要被封裝在一個嵌套函數中,這樣外函數在兩種情況下都可以返回。 – isedev 2014-10-05 19:46:32

2

的問題是與線

return it.takewhile(lambda x: x < n, get_primes()) 

由於它是一臺發電機,返回的東西停止執行,並引發StopIteration異常()。您需要返回生成器中的值

#return all the values from generator 
for a in it.takewhile(lambda x: x < n, get_primes()) 
    yield a 

return