当下一个方法应该返回两个生成器的值时,如何为类创建下一个方法?
Posted
技术标签:
【中文标题】当下一个方法应该返回两个生成器的值时,如何为类创建下一个方法?【英文标题】:How to create a next method for a class when the next method is supposed to return the values of two generators? 【发布时间】:2018-02-07 13:12:48 【问题描述】:我有以下示例,其中一个类的下一个方法应该从两个生成器返回值:
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)
怎么了?有没有更雄辩的方式来写这门课?
【问题讨论】:
这个类的实例应该是什么?迭代器,还是多用途迭代器?为什么你有这个类而不是编写另一个生成器? 你打算通过编写这个类来创建什么行为? 我基本上想从两个单独的函数返回值。我不想在 next 方法中编写这两个函数,这些函数可以是生成器。有意义吗? 你会接受你得到的答案之一吗?如果不是,为什么会这样? 对不起。我不知道我需要接受答案。 【参考方案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))
【讨论】:
谢谢。我认为我的例子是不言自明的。我的下一个方法应该从两个函数返回值。我不想在下一个方法体中编写这些函数。这些函数可以潜在地编写为生成器。这有意义还是我错过了什么?什么不清楚? 提供的解决方案不能做到这一点吗? 它有效,但既然你提到它不清楚我在做什么,我想知道我的方法是否错误。有没有其他方法可以实现这个目标? 好吧,如果你只想同时迭代两个生成器,我不知道你需要一个类的所有样板。为什么不直接做类似foo = zip(range(10),range(11,20))
.【参考方案2】:
您的代码不起作用,因为它每次在调用__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)
【讨论】:
以上是关于当下一个方法应该返回两个生成器的值时,如何为类创建下一个方法?的主要内容,如果未能解决你的问题,请参考以下文章