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

时间:2018-09-08 18:13:19

标签: python

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

git for-each-ref

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

int smallest=Integer.MAX_VALUE;//assume smallest to be largest integer
for(int i=0;i<100;i++){
    int num=sc.nextInt();//this will run 100 times and hence will input 100 number
    if(num<smallest){//if number is smaller than smallest then num is smallest
       smallest=num; 
    }
}
System.out.println(smallest);

为什么我必须在循环内调用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__函数,则循环将永远运行。

1 个答案:

答案 0 :(得分:4)

由于使用__next__,您的yield方法本身是生成器函数。它必须是使用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-这表示迭代已结束。