检查元素是否已在队列中

时间:2013-05-12 10:29:40

标签: python queue

我在python中使用Queue库,我想保持队列条目的唯一性。

因此我想在添加它之前检查队列中是否还没有'某事',本质上是一个在Queue库上工作的函数:

queue = Queue.Queue()
def in_queue(u):
  return u in queue

或者,我应该使用不同的库/方法来实现这一目标吗?

1 个答案:

答案 0 :(得分:35)

无法迭代或以其他方式检查标准Queue类。

然而,它是为了扩展而构建的。

首先,如果你看一下source(从文档链接),就会有钩子方法_init_qsize_put和{{1}您可以覆盖以更改实现。查看主类下面的子类,您可以看到它们是如何做到的。

因此,一件简单的事情就是将_get实现替换为deque

set

(我没有实施class SetQueue(Queue.Queue): def _init(self, maxsize): self.queue = set() def _put(self, item): self.queue.add(item) def _get(self): return self.queue.pop() ,因为默认的_qsize没问题。)

现在您不必检查,只需将其添加到队列中,如果它已经存在,它将被忽略。

当然,这有不足之处,不再对队列进行排序。但您可以使用return len(self.queue)(类似于OrderedSet中的OrderedDict)来解决此问题。有一个recipe来自collections文档。一旦你有了:

collections

如果您确实希望能够检查队列中的值,可以为其添加方法:

class OrderedSetQueue(Queue.Queue):
    def _init(self, maxsize):
        self.queue = OrderedSet()
    def _put(self, item):
        self.queue.add(item)
    def _get(self):
        return self.queue.pop()

但是,这会在您的代码中引发竞争条件。例如,如果您这样做:

class CheckableQueue(Queue.Queue): # or OrderedSetQueue
    def __contains__(self, item):
        with self.mutex:
            return item in self.queue

检查时,if x not in my_queue: my_queue.put(x) 总是可能不在队列中,但是当您调用x时,队列中的 。事实上,不会不安全的这个函数的唯一用途是某种乐观检查(如果值不在队列中现在,做一些昂贵的工作,然后尝试添加它,接受如果在此期间添加了值则浪费了工作) - 同样的原因put存在。

保证安全的唯一方法是将两个操作放在一起锁定:

Queue.full()

但是在这一点上,你首先要打败使用with my_queue.mutex: if x not in my_queue: my_queue.put(x) 的目的。 (您还要依赖于Queue是一个递归可输入的互斥锁的事实。)最好将操作添加为Queue.mutex子类的方法。

如果总是想先检查并仅在不存在的情况下添加,Queue是更好的方法。