Python 循环如何防止生成器抛出StopIteration异常?

Python 循环如何防止生成器抛出StopIteration异常?,python,numpy,iterator,generator,cycle,Python,Numpy,Iterator,Generator,Cycle,考虑到这个例子: from itertools import cycle def foo(): for i in range(3): yield i c = cycle(foo()) next(c) # -> 0 next(c) # -> 1 next(c) # -> 2 [StopIteration should be thrown here normally] next(c) # -> 0 ... 如何循环防止发电机通过停止迭代

考虑到这个例子:

from itertools import cycle

def foo():
    for i in range(3):
        yield i

c = cycle(foo())

next(c)  # -> 0
next(c)  # -> 1
next(c)  # -> 2 [StopIteration should be thrown here normally]
next(c)  # -> 0
...
如何循环
防止发电机通过
停止迭代
励磁?我认为生成器只能执行一次,因为生成器只返回其当前值并继续运行

当抛出
StopIteration
时,
cycle
是否只是重新创建生成器?当我迭代大型numpy阵列时,这是否会成为一个问题(效率低下)

第二个问题:这是一种使用迭代器/生成器循环大型数据集的“pythonic”方式吗?或者我应该直接将循环逻辑传输到生成器本身(比如定义索引和使用while循环重置索引)

我的目的是高效地遍历大型数据集(主要是numpy数组;>100.000个条目)

如何循环
防止发电机通过
停止迭代
励磁

没有。生成器到达其末端并以正常的
StopIteration
退出
cycle
存储生成器的输出,当
cycle
看到
StopIteration
时,它会从生成器生成的内容的存储历史切换到生成项目

如何循环
防止发电机通过
停止迭代
励磁


没有。生成器到达其末端并以正常的
StopIteration
退出<代码>循环存储生成器的输出,当<代码>循环看到<代码>停止迭代,它会从生成器生成的内容的存储历史切换到生成项。

用户2357112
已回答您的第一个问题

至于你的第二个,对于一个像numpy数组这样的容器,我们可以创建一个等价于循环,它不需要在内存中创建额外的副本。请注意,这不适用于生成器!如果我们要反复使用它们,或者至少有办法按需生成它们,我们就必须将副本存储在某个地方

def cycle(container):
    if iter(container) is container:
        raise TypeError('need a container, not a generator')
    while True:
       yield from container



# this works correctly for a container
for i, char in enumerate(cycle('abc')):
    print(char)
    if i > 10:
        break
假设我们希望重复读取文件,而不在内存中创建每一行的副本

我们可以创建一个实现
\uu iter\uuu
的“包装类”,然后使用新的
循环
方法

class Reader():
    def __init__(self, path, *args, **kwargs):
        self.path, self.args, self.kwargs = path, args, kwargs
    def __iter__(self):
        with open(self.path, *self.args, **self.kwargs) as file:
            yield from file

 #eg:
 for line in cycle(Reader(filepath)):
     #somecode

user2357112
已回答您的第一个问题

至于你的第二个,对于一个像numpy数组这样的容器,我们可以创建一个等价于循环,它不需要在内存中创建额外的副本。请注意,这不适用于生成器!如果我们要反复使用它们,或者至少有办法按需生成它们,我们就必须将副本存储在某个地方

def cycle(container):
    if iter(container) is container:
        raise TypeError('need a container, not a generator')
    while True:
       yield from container



# this works correctly for a container
for i, char in enumerate(cycle('abc')):
    print(char)
    if i > 10:
        break
假设我们希望重复读取文件,而不在内存中创建每一行的副本

我们可以创建一个实现
\uu iter\uuu
的“包装类”,然后使用新的
循环
方法

class Reader():
    def __init__(self, path, *args, **kwargs):
        self.path, self.args, self.kwargs = path, args, kwargs
    def __iter__(self):
        with open(self.path, *self.args, **self.kwargs) as file:
            yield from file

 #eg:
 for line in cycle(Reader(filepath)):
     #somecode

这听起来像是
循环
如果我在大数据集上使用它,内存效率会很低吗?我的意思是它必须存储
yield
返回的每一个值,然后呢?@daniel451:它实际上没有任何其他选项。您可能有其他选择,因为您有更多的上下文,但是
cycle
没有。如果在大型数据集上使用
cycle
的话,这听起来像是内存效率非常低?我的意思是它必须存储
yield
返回的每一个值,然后呢?@daniel451:它实际上没有任何其他选项。您可能有其他选项,因为您有更多的上下文,但
cycle
没有。最后,您可以使用额外的while或for循环,而不是
cycle
,如果它是生成器,则首先调用list()或tuple()。这不太“干净”,但对您的目标受众来说可能更清楚,这取决于他们对python和itertool风格习惯用法的熟悉程度。最后一点,您可以使用额外的while或for循环,而不是
cycle
,如果它是生成器,则首先调用list()或tuple()。这不太“干净”,但对您的目标受众来说可能更清楚,这取决于他们对python和itertool风格习惯用法的熟悉程度。