【问题标题】:Round robin on iterable可迭代循环
【发布时间】:2016-03-02 12:09:34
【问题描述】:

考虑以下简单的循环实现:

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 类中的可迭代对象,这也会影响现有的迭代器。

例如假设当我使用迭代器中的值时,集合中的一台机器变得不可用,我想阻止它被返回。

我能想到的唯一解决方案是实现一个单独的Iterator 类。当然,这仍然是一个问题,当所有机器都变得不可用并且无法返回更多值时该怎么办(StopIteration 异常?)。

【问题讨论】:

  • 机器不可用时为什么不能使用continue语句?
  • @AswinMurugesh 是的,但请考虑(尽管我承认在我的问题中没有指定)可能有多个线程使用 RR 代码,我想向我的 RR 类发出信号,其中之一机器变得不可用,无需单独通知每个线程。 (我不确定这实际上是否更清楚......)
  • 在这种情况下,你有一个类的静态变量,它可能是一组不可用的机器,并在 continue 语句之前将机器号添加到集合中

标签: python-3.x


【解决方案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()

【讨论】:

    猜你喜欢
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 2017-06-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    相关资源
    最近更新 更多