当我创建基于类的生成器时,为什么我必须调用下一个?



我是Python的新手,我正在阅读Python Tricks一书。在关于生成器的章节中,它给出了以下示例(有一些更改(

class BoundedGenerator:
def __init__(self, value, max_times):
self.value = value
self.max_times = max_times
self.count = 0
def __iter__(self):
return self
def __next__(self):
if self.count < self.max_times:
self.count += 1
yield self.value

之后,我编写一个循环,实例化生成器并打印值:

for x in BoundedGenerator('Hello world', 4):
print(next(x))

为什么我必须在循环内调用next(X)

我(认为(我知道__iter__函数将在循环线定义中调用,并且__next__将在每次迭代中调用,但我不明白为什么我必须在循环内再次调用下一个。这不是多余的吗? 如果我不调用__next__函数,我的循环将永远运行。

由于使用了yield,您的__next__方法本身就是一个生成器函数。它必须是改用return的常规函数。

def __next__(self):
if self.count < self.max_times:
self.count += 1
return self.value   # return to provide one value on call
raise StopIteration     # raise to end iteration

迭代时,python 调用iter.__next__来接收新值。如果这是一个生成器函数,则调用仅返回生成器。这与任何其他生成器函数的行为相同:

>>> def foo():
...    yield 1
...
>>> foo()
<generator object foo at 0x106134ca8>

这需要您在生成器上调用next才能实际获取值。同样,由于您将BoundedGenerator.__next__定义为生成器函数,因此每个迭代步骤仅提供一个新的生成器。

使用return而不是yield确实返回值,而不是生成所述值的生成器。此外,您应该在完成后raise StopIteration- 这表示迭代结束。

最新更新