Python:检查生成器中是否存在对象

Jud*_*ing 1 python list generator range

我有一个错误是由检查"如果x在发电机中"的变化结果引起的

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)
Run Code Online (Sandbox Code Playgroud)

这给出了输出:

True
False
False
False
False
Run Code Online (Sandbox Code Playgroud)

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

>>> hundred_generator = range(1,100)
>>> 50 in hundred_generator
True
>>> 50 in hundred_generator
True
>>> 50 in hundred_generator
True
Run Code Online (Sandbox Code Playgroud)

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

shx*_*hx2 6

当您遍历生成器的元素时,您将使用它们.

试试这个:

len(list(first_hundred_primes)) > 0
=> True
len(list(first_hundred_primes)) > 0
=> False
Run Code Online (Sandbox Code Playgroud)

也就是说,你第一次使用元素时会消耗元素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.由于它代表集合而不是生成器,因此您可以多次迭代它,而不会"消耗"元素.