考虑以下简单的循环实现:
from itertools import chain, repeat
class RoundRobin:
def __init__(self, iterable):
self._iterable = set(iterable)
def __iter__(self):
for value in chain.from_iterable(repeat(self._iterable)):
yield value
使用示例:
machines = ['test1', 'test2',
'test3', 'test4']
rr_machines = RoundRobin(machines)
for machine in rr_machines:
# Do something
pass
虽然这有效,但我想知道是否有办法修改RoundRobin
类中的迭代,这也会影响现有的迭代器。
E.g。假设当我从迭代器中消耗值时,集合中的一台机器变得不可用,我想阻止它被返回。
我能想到的唯一解决方案是实现一个单独的Iterator
类。当然,当所有机器都变得不可用并且不能返回更多值时(StopIteration
异常?),仍然存在问题该怎么办。
答案 0 :(得分:1)
Itertools'repeat
制作底层迭代器的副本,在本例中,是包含元素的set
。
这是创建repeat
的另一个实现的一个主题,它将在整个集合的每次迭代中重新创建这样的副本。这是可能的,因为在这种情况下,我们知道要重复的迭代器是一个容器,而itertools.repeat
必须使用任何迭代器(所以,记住第一次迭代的值):
def mutable_repeat(container):
while True:
for item in container.copy():
yield item
只需使用此代替重复,您就可以对self._iterable
集进行“即时”更改,并且可以在该集合中添加/删除新值。 (虽然删除的值最有可能在删除之前最后一次发布)
如果您需要防止发出删除的值一次,您可以通过添加更多逻辑来轻松防范它 -
而不是直接从课外与self._iterable
进行迭代,你可以这样做:
class RoundRobin:
def __init__(self, iterable):
self._iterable = set(iterable)
self._removed = set()
def __iter__(self):
for value in chain.from_iterable(self.repeat()):
yield value
def remove(self, item):
self._removed.add(item)
self._iterable.remove(item)
def add(self, item):
self._iterable.add(item)
def repeat(self):
while True:
for item in self._iterable.copy():
if not item in self._removed:
yield item
self._removed = set()