当下一个方法应该返回两个生成器的值时,如何为类创建下一个方法?

时间:2017-08-29 23:59:34

标签: python iterator generator iterable

我有以下示例,其中类的下一个方法应该从两个生成器返回值:

class Test():
    def __next__(self):
        g1, g2 = self._gen1(), self._gen2() 
        return next(g1), next(g2)

    def _gen1(self):
        i = 0
        while True:
            yield i
            i += 2

    def _gen2(self):
        i = 1
        while True:
            yield i
            i += 2

但是,当我为此类调用next时,值不会递增。

>>> t = Test()
>>> next(t)
>>> (0, 1)
>>> next(t)
>>> (0, 1)

有什么问题?有没有更有说服力的方式来写这门课程?

2 个答案:

答案 0 :(得分:1)

虽然我不知道你想要完成什么,但这是一个清理版本(我认为)可以做你想要的。

class Test():
    def __init__(self):
        self.g1 = self._gen2() 
        self.g2 = self._gen1()
    def __next__(self):
        return next(self.g1), next(self.g2)

    def _gen1(self):
        i = 0
        while True:
            yield i
            i += 2

    def _gen2(self):
        i = 1
        while True:
            yield i
            i += 2

t = Test()

print(next(t))           
print(next(t))           
print(next(t))  

答案 1 :(得分:0)

您的代码无法正常工作,因为它会在每个时间__next__()重新创建生成器函数,这会在下一个next()值之前将它们有效地重置为初始状态退回:

    def __next__(self):
        g1, g2 = self._gen1(), self._gen2()  # Don't do this here.
        return next(g1), next(g2)

您可以通过添加__init__()方法并在其中初始化它来解决此问题:

class Test:
    def __init__(self):
        self.g1, self.g2 = self._gen1(), self._gen2()  # Initialize here.

    def __next__(self):
        return next(self.g1), next(self.g2)
    ...

一个更有说服力,更简洁的方法来做同样可以避免问题的方法是使用内置zip() function创建一个“生成器迭代器”,它将从每个生成器返回每个生成器的下一个值对时间被称为。另一个优点是只需更改__init__()方法即可轻松扩展以处理更多生成器。

这就是我的意思:

class Test:
    def __init__(self):
        self.generators = zip(self._gen1(), self._gen2())

    def __next__(self):
        return next(self.generators)

    def _gen1(self):
        i = 0
        while True:
            yield i
            i += 2

    def _gen2(self):
        i = 1
        while True:
            yield i
            i += 2

t = Test()
for _ in range(3):
    print(next(t))

输出:

(0, 1)
(2, 3)
(4, 5)