Какая разница между 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 специализирован для своей цели, он не является потокобезопасным (как указано в другом ответе здесь.)