【问题标题】:How to put items into priority queues?如何将项目放入优先队列?
【发布时间】:2012-03-06 13:43:59
【问题描述】:

在 Python 文档中,

首先检索最低值的条目(最低值的条目是sorted(list(entries))[0] 返回的条目)。条目的典型模式是以下形式的元组:(priority_number, data)

似乎队列将按优先级然后数据排序,这可能并不总是正确的。假设数据“item 2”在“item 1”之前入队,item 1 仍将先行。在另一个文档页面heapq 中,它建议使用计数器。所以我会像entry = [priority, count, task]一样存储我的数据。有没有类似的东西

PriorityQueue.put(item, priority)

那我就不需要自己实现排序了吗?

【问题讨论】:

    标签: python queue


    【解决方案1】:

    如果不适合对字符串数据进行字母数字排序,只需将元组的第二项用作次要优先级。当您有多个具有相同优先级的项目时,日期/时间优先级将为您提供一个优先级队列,该队列回退到 FIFIO 队列。这是一些仅具有次要数字优先级的示例代码。在第二个位置使用日期时间值是一个非常微不足道的更改,但如果您无法使其正常工作,请随时在 cmets 中戳我。

    代码

    import Queue as queue
    
    prio_queue = queue.PriorityQueue()
    prio_queue.put((2, 8, 'super blah'))
    prio_queue.put((1, 4, 'Some thing'))
    prio_queue.put((1, 3, 'This thing would come after Some Thing if we sorted by this text entry'))
    prio_queue.put((5, 1, 'blah'))
    
    while not prio_queue.empty():
        item = prio_queue.get()
        print('%s.%s - %s' % item)
    

    输出

    1.3 - This thing would come after Some Thing if we didn't add a secondary priority
    1.4 - Some thing
    2.8 - super blah
    5.1 - blah
    

    编辑

    如果您使用时间戳来伪造 FIFO 作为次要优先级,使用日期如下所示。我说假是因为它只是大约 FIFO,因为在时间上非常接近添加的条目可能不会完全 FIFO。我添加了一个短暂的睡眠,所以这个简单的例子以合理的方式工作。希望这有助于作为另一个示例,说明您如何获得所需的订单。

    import Queue as queue
    import time
    
    prio_queue = queue.PriorityQueue()
    prio_queue.put((2, time.time(), 'super blah'))
    time.sleep(0.1)
    prio_queue.put((1, time.time(), 'This thing would come after Some Thing if we sorted by this text entry'))
    time.sleep(0.1)
    prio_queue.put((1, time.time(), 'Some thing'))
    time.sleep(0.1)
    prio_queue.put((5, time.time(), 'blah'))
    
    while not prio_queue.empty():
        item = prio_queue.get()
        print('%s.%s - %s' % item)
    

    【讨论】:

      【解决方案2】:

      据我所知,您要查找的内容并非开箱即用。无论如何,请注意实施起来并不难:

      from Queue import PriorityQueue
      
      class MyPriorityQueue(PriorityQueue):
          def __init__(self):
              PriorityQueue.__init__(self)
              self.counter = 0
      
          def put(self, item, priority):
              PriorityQueue.put(self, (priority, self.counter, item))
              self.counter += 1
      
          def get(self, *args, **kwargs):
              _, _, item = PriorityQueue.get(self, *args, **kwargs)
              return item
      
      
      queue = MyPriorityQueue()
      queue.put('item2', 1)
      queue.put('item1', 1)
      
      print queue.get()
      print queue.get()
      

      示例输出:

      item2
      item1
      

      【讨论】:

      • 我是 Python 新手,对我来说,PriorityQueue.__init__(self) 似乎正在调用静态方法。有类似parent.__init__(self) 的东西吗?
      • 哦,或者我应该解释为:我正在调用传入self的静态方法。如果我调用对象方法,我就不需要了?
      • PriorityQueue.__init__(self) 写成super(MyPriorityQueue, self).__init__() 更恰当,但它是有效的。
      • @larsmans 我试过了,但似乎PriorityQueue 是一个老式的类,它不适用于super
      • 看来你是对的。相当令人惊讶;请原谅我之前的评论。
      【解决方案3】:

      我做了这样的事情来完成类似于 gfortune 的 FIFO,但不需要到处调用 time.time():(仅限 Python 3)

      import time
      from dataclasses import dataclass, field
      
      @dataclass(order=True)
      class PrioritizedItem:
          prio: int
          timestamp: float = field(init=False, default_factory=time.time)
          data: object = field(compare=False)
      

      现在你可以这样做了:

      import queue
      
      item1 = PrioritizedItem(0, "hello world")
      item2 = PrioritizedItem(0, "what ever")
      q = queue.PriorityQueue()
      q.put(item1)
      q.put(item2)
      

      并且可以肯定,它们将始终以相同的顺序被提取。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-02-24
        • 1970-01-01
        • 2011-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多