简体   繁体   English

Python 如何部分使用可迭代生成器(没有 `next`)?

[英]Python how to partially consume an iterable generator (without `next`)?

I have a class acting as an iterable generator (as per Best way to receive the 'return' value from a python generator ) and I want to consume it partially with for loops.我有一个 class 作为可迭代生成器(根据Best way to receive the 'return' value from a python generator ),我想用for循环部分地使用它。

I can't use next (like Python -- consuming one generator inside various consumers ) because the first partial consumption uses a library that only takes iterators.我不能使用next (比如Python——在各种消费者中使用一个生成器),因为第一个部分使用的是一个只接受迭代器的库。 How can I continue using the generator starting from where the library function left off?如何从库 function 停止的地方开始继续使用生成器?

(Related: Pause Python Generator , Is there a way to 'pause' or partially consume a generator in Python, then resume consumption later where left off? ) (相关:暂停 Python 生成器有没有办法“暂停”或部分消耗 Python 中的生成器,然后稍后从停止的地方恢复消耗?

class gen(): # https://stackoverflow.com/q/34073370
    def __iter__(self):
        for i in range(20):
            yield i

# I want to partially consume in the first loop and finish in the second
my_gen_2 = gen()
for i in my_gen_2:  # imagine this is the internal implementation of the library function
    print(i)
    if i > 10:      # the real break condition is when iterfzf recieves user input
        break

for i in my_gen_2:  # i'd like to process the remaining elements instead of starting over
    print('p2', i)

# the confusion boils down to this
my_gen = gen()
for i in my_gen:
    print(i)    # prints 1 through 20 as expected
for i in my_gen:
    print('part two', i)    # prints something, even though the generator should have been "consumed"?

Every time you iterable generator in a loop, you get a new iterator.每次循环中的迭代生成器,都会得到一个新的迭代器。 For example:例如:

class gen(): # https://stackoverflow.com/q/34073370
    def __init__(self):
        self.count = 0
    def __iter__(self):
        self.count += 1
        print("Hallo iter {0}".format(self.count))
        yield self.count


my_gen = gen()
>>> for i in my_gen:
...    pass
Hallo iter 1
>>> for i in my_gen:
...    pass
Hallo iter 2

If you want to use the old iterator, just work with gen().__iter__()如果你想使用旧的迭代器,只需使用gen().__iter__()

>>> my_gen = gen().__iter__()
>>> for i in my_gen:
...    pass
Hallo iter 1
>>> for i in my_gen:
...    pass

As @napuzba pointed out, __iter__ returns a whole new generator every time it is used.正如@napuzba 指出的那样, __iter__每次使用时都会返回一个全新的生成器。 Instead, store the state in self :相反,将 state 存储在self中:

class gen():
    def __init__(self):
        self.count = 0
    def __iter__(self):
        while self.count < 20:
            self.count += 1
            yield self.count

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM