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风格习惯用法的熟悉程度。