Python 检查元素是否已经在队列中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16506429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check if element is already in a Queue
提问by Riley Kidd
I am using the Queuelibrary in python and I want to keep queue entries unique.
我Queue在 python 中使用这个库,我想保持队列条目的唯一性。
As such I want to check 'something' isn't already in the queue before adding to it, essentially a function like this which works on the Queue library:
因此,我想在添加到队列之前检查“某物”是否已经在队列中,本质上是这样的函数,它适用于队列库:
queue = Queue.Queue()
def in_queue(u):
return u in queue
Or, should I be using a different library/method to achieve this?
或者,我应该使用不同的库/方法来实现这一点吗?
采纳答案by abarnert
The standard Queueclass can't be iterated or otherwise checked.
Queue不能迭代或以其他方式检查标准类。
However, it was built to be extended.
但是,它是为扩展而构建的。
First, if you look at the source(which is linked from the docs), there are hook methods _init, _qsize, _putand _getthat you can override to change the implementation. Look at the subclasses below the main class, and you can see how they do this.
首先,如果你看一下源(这是从文档的链接),有钩的方法_init,_qsize,_put并且_get可以覆盖改变实现。看看主类下面的子类,你可以看到它们是如何做到的。
So, one easy thing to do is replace the dequeimplementation with a set:
因此,一件简单的事情就是用以下代码替换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()
(I didn't implement _qsizebecause the default return len(self.queue)is fine.)
(我没有实现,_qsize因为默认return len(self.queue)值很好。)
Now you don't have to check, just add it to the queue, and it'll be ignored if it's already there.
现在您不必检查,只需将其添加到队列中,如果它已经存在,它将被忽略。
Of course this has the down side that the queue is no longer ordered. But you can solve that by using an OrderedSet(similar to the OrderedDictin collections). There's a recipethat's linked from the collectionsdocs. Once you have that:
当然,这有一个不利方面,即不再对队列进行排序。但是您可以通过使用OrderedSet(类似于OrderedDictin 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()
If you actually want to be able to check values within a queue, you can add a method for that:
如果您确实希望能够检查队列中的值,您可以为此添加一个方法:
class CheckableQueue(Queue.Queue): # or OrderedSetQueue
def __contains__(self, item):
with self.mutex:
return item in self.queue
However, this invites race conditions in your code. For example, if you do this:
但是,这会在您的代码中引发竞争条件。例如,如果您这样做:
if x not in my_queue:
my_queue.put(x)
It's always possible that xwas not in the queue when you checked, but wasin the queue when you called put. In fact, the only use of this function which wouldn'tbe unsafe is some kind of optimistic checking (if the value isn't in the queue now, do some expensive work, then try to add it, accepting that the work is wasted if the value has been added in the meantime)—the same reason Queue.full()exists.
它总是可能的,x是不在队列中,当您检查,但就是在排队的时候你打电话put。实际上,只有使用此功能,其中不会是不安全的某种乐观检查的(如果该值不在队列中,现在,做一些费时的工作,然后尝试添加它,接受这项工作是浪费如果在此期间已添加该值)-Queue.full()存在相同的原因。
The only way to make this safe is to put both operations together under a lock:
确保此安全的唯一方法是将两个操作放在一起锁定:
with my_queue.mutex:
if x not in my_queue:
my_queue.put(x)
But at this point, you're defeating the purpose of using Queuein the first place. (You're also depending on the fact that Queue.mutexis a recursively-enterable mutex.) Better to add the operation as a method of your Queuesubclass.
但是在这一点上,您首先违背了使用的目的Queue。(您还依赖于Queue.mutex可递归输入的互斥锁这一事实。)最好将该操作添加为您的Queue子类的方法。
And if you alwayswant to check first and add only if it's not there, OrderedSetQueueis a better way to do that.
如果您总是想先检查并仅在它不存在时添加,这OrderedSetQueue是一种更好的方法。

