【问题标题】:Python: check if object exists in generatorPython:检查生成器中是否存在对象
【发布时间】:2014-08-24 16:25:54
【问题描述】:

我遇到了一个错误,它是由检查“if x in generator”的结果变化引起的

def primes(upper_limit):
    for n in range(2, upper_limit):
        if all(n % i > 0 for i in range(2, n)):
            yield n

first_hundred_primes = primes(100)

print(5 in first_hundred_primes)
print(5 in first_hundred_primes)
print(5 in first_hundred_primes)
print(5 in first_hundred_primes)
print(5 in first_hundred_primes)

这给出了输出:

True
False
False
False
False

我假设不是要检查一个对象是否存在于生成器中,但如果是这种情况,为什么它不抛出一些错误,为什么它会起作用?

>>> hundred_generator = range(1,100)
>>> 50 in hundred_generator
True
>>> 50 in hundred_generator
True
>>> 50 in hundred_generator
True

我通常在检查其中是否存在某个对象(以加快检查速度)之前将生成器变成一个集合,这可以解决问题,但我非常想知道这里发生了什么?

【问题讨论】:

    标签: python list range generator


    【解决方案1】:

    当您迭代生成器的元素时,您使用它们。

    试试这个:

    len(list(first_hundred_primes)) > 0
    => True
    len(list(first_hundred_primes)) > 0
    => False
    

    即第一次使用 in (迭代它们)时,您已经完成了元素的使用,或者列出了最多 5 个的所有元素,因此生成器将不会在此之后再次生成 5。第二次之后,它不会再生成任何东西了。

    您的选择:

    1. 在使用之前将您的生成器转换为列表(或集合):first_hundred_primes = list(first_hundred_primes)
    2. 每次创建一个新的生成器:5 in primes(100); 5 in primes(100); ...
    3. 使用itertools.tee

    编辑:

    关于range 的问题:range 不是生成器。

    在 python2 中,它只是返回一个列表。没问题。

    在python3中,它返回一个看起来像一个集合的特殊对象。它不必实际存储范围内的所有数字,它只是根据定义范围的规则实现列表操作。例如。 len 实现为 stop-start。由于它代表一个集合,而不是一个生成器,因此您可以对其进行多次迭代,而不会“消耗”元素。

    【讨论】:

    • 哇,很高兴知道这一点。至于我的第二个例子,百代生成器 = range(1,100)。元素似乎没有被“消耗”,每次都在百代生成器中成功 50,您对那里发生的事情有任何见解吗?
    猜你喜欢
    • 2020-03-23
    • 1970-01-01
    • 2012-07-27
    • 2013-09-26
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多