【问题标题】:Setting a limit on an infinite generator in Python在 Python 中设置无限生成器的限制
【发布时间】:2014-11-30 03:12:40
【问题描述】:

我正在尝试使下面的生成器能够设置返回数字的上限。

调用 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

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    这里:

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

    由于这是一个生成器,它需要 yield 这些值而不是 returning 它们。根据您的 Python 版本,您也许可以使用 yield from 语法。

    以下内容可能对背景阅读有用:Return in generator together with yield in Python 3.3

    【讨论】:

    • 虽然在这里用yield 替换return 不会有预期的行为(生成器将产生另一个生成器作为第一个值)。
    • @isedev:yield from 将直接替代 return(普通的 yield,当然不会)。
    • 当然,如果您可以使用yield from,请同意。否则,实际的生成器将需要包装在嵌套函数中,以便外部函数在两种情况下都可以return
    • 有道理。我想我已经假设因为return 语句会发生在任何yield 语句之前,它会很高兴地返回我的临时迭代器。从链接的线程来看,它似乎不是那样工作的。谢谢。
    【解决方案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 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-27
      • 2020-12-25
      • 2021-01-27
      • 1970-01-01
      • 2017-05-13
      • 2018-08-10
      • 1970-01-01
      相关资源
      最近更新 更多