循环如何防止生成器抛出 StopIteration 异常?
How does cycle prevent a generator from throwing a StopIteration exception?
考虑这个例子:
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
...
cycle
如何防止发电机通过 StopIteration
励磁?我认为生成器只能执行一次,因为生成器仅 returns 其当前值并继续前进。
抛出 StopIteration
时 cycle
只是重新创建生成器吗?当我遍历大型 numpy 数组时,这会成为一个问题(效率低下)吗?
第二个问题:这是"pythonic"用iterators/generators循环大数据集的方法吗?或者我应该将循环逻辑直接转移到生成器本身(比如定义索引和使用带有重置索引的 while 循环)?
我的目的是有效地循环大型数据集(主要是 numpy 数组;>100.000 个条目)。
How does cycle
prevent the generator from exciting via a StopIteration
?
没有。生成器到达终点并正常退出 StopIteration
。 cycle
存储生成器的输出,当 cycle
看到 StopIteration
时,它会切换到从生成器生成的存储历史记录中生成项目。
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
假设我们想重复读取文件而不在内存中创建每一行的副本。
我们可以创建一个实现 __iter__
的 'wrapper class',然后使用我们新的 cycle
方法。
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
考虑这个例子:
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
...
cycle
如何防止发电机通过 StopIteration
励磁?我认为生成器只能执行一次,因为生成器仅 returns 其当前值并继续前进。
抛出 StopIteration
时 cycle
只是重新创建生成器吗?当我遍历大型 numpy 数组时,这会成为一个问题(效率低下)吗?
第二个问题:这是"pythonic"用iterators/generators循环大数据集的方法吗?或者我应该将循环逻辑直接转移到生成器本身(比如定义索引和使用带有重置索引的 while 循环)?
我的目的是有效地循环大型数据集(主要是 numpy 数组;>100.000 个条目)。
How does
cycle
prevent the generator from exciting via aStopIteration
?
没有。生成器到达终点并正常退出 StopIteration
。 cycle
存储生成器的输出,当 cycle
看到 StopIteration
时,它会切换到从生成器生成的存储历史记录中生成项目。
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
假设我们想重复读取文件而不在内存中创建每一行的副本。
我们可以创建一个实现 __iter__
的 'wrapper class',然后使用我们新的 cycle
方法。
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