我有下面的例子,其中一个类的下一个方法应该返回来自两个生成器的值:
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)
怎么了?有没有比这门课更有说服力的写作方法?
虽然我不知道你想要实现什么,但这里有一个干净的版本,(我认为(可以满足你的需求。
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))
您的代码不起作用,因为它在每次调用__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()
函数创建一个"生成器迭代器",每次调用它时都会从每个生成器返回下一对值。另一个优点是,只需更改__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)