Какая разница между heapq и PriorityQueue в python?

В python есть встроенный алгоритм heapq, который дает вам push, pop, nlargest, nsmallest... и т.д., которые вы можете применить к спискам. Однако существует класс queue.PriorityQueue, который, как представляется, поддерживает более или менее ту же функциональность. Какая разница, и когда вы будете использовать один над другим?

Ответы

Ответ 1

Queue.PriorityQueue - это поточно-безопасный класс, а модуль heapq не гарантирует безопасность потока. Из документации Queue:

Модуль Queue реализует многопроцессорные очереди с несколькими потребителями. Это особенно полезно при программировании с резьбой, когда информация должна быть безопасно заменена между несколькими потоками. Класс Queue в этом модуле реализует все необходимые семантики блокировки. Это зависит от наличия поддержки потоков в Python; см. модуль threading.

Модуль heapq не имеет блокировки и работает со стандартными объектами list, которые не предназначены для потоковой защиты.

Фактически реализация PriorityQueue использует heapq под капотом для выполнения всех операций приоритизации с базовым классом Queue, обеспечивающим блокировку, чтобы сделать эту потокобезопасную. Подробнее см. исходный код.

Это ускоряет работу модуля heapq; нет накладных расходов на блокировку. Кроме того, вы можете свободно использовать различные функции heapq по разным новым способам, PriorityQueue предлагает только функцию прямой очереди.

Ответ 2

queue.PriorityQueue является частичной оболочкой вокруг класса heapq.

Другими словами, queue.PriorityQueue на самом деле является heapq, помещенным в модуль очереди с несколькими переименованными методами, чтобы сделать heapq более простым в использовании, подобно обычной очереди.

В heapq вы используете метод heappush() для добавления нового элемента и метода heappop() для его удаления. Это не очень похоже на очередь, поэтому queue.PriorityQueue позволяет использовать обычные методы очереди, такие как push и pop, чтобы сделать то же самое.

Есть некоторые функции heapq, которые не переносятся в queue.PriorityQueue, такие как heappushpop() и heapreplace(), но вы менее любите их использовать. Если вам это нужно (и я делаю в моем текущем проекте), используйте heapq, а не queue.PriorityQueue.

Кроме того, поскольку heapq специализирован для своей цели, он не является потокобезопасным (как указано в другом ответе здесь.)