You can use the heapq module to perform operations like finding the nlargest and nsmallest items in a collection. A heap is a tree-based data structure for which every parent node has a value less than or equal to any of its children. You can use it to make queues.

import heapq

nums = [3, 4, 7, 1, 4, 9, 0, 2, -4, 6, -7, -1]
print(heapq.nlargest(3, nums))
## [9, 7, 6]
print(heapq.nsmallest(3, nums))
## [-7, -4, -1]

You can convert a list into a heap.

nums = list(nums)
heapq.heapify(nums)
nums
## [-7, -4, -1, 1, 4, 7, 0, 2, 3, 6, 4, 9]

For more complex data structures, you can use the key parameter.

portfolio = [
  {"name": "IBM", "shares": 100, "price": 91.1},
  {"name": "AAPL", "shares": 40, "price": 534.2},
  {"name": "FB", "shares": 10, "price": 130.9},
  {"name": "YHOO", "shares": 50, "price": 56.8},
  {"name": "GOOG", "shares": 23, "price": 678.4},
  {"name": "AMZ", "shares": 56, "price": 1234.5},
]

cheap = heapq.nsmallest(3, portfolio, key=lambda s: s["price"])
expensive = heapq.nlargest(3, portfolio, key=lambda s: s["price"])
cheap
## [{'name': 'YHOO', 'shares': 50, 'price': 56.8}, {'name': 'IBM', 'shares': 100, 'price': 91.1}, {'name': 'FB', 'shares': 10, 'price': 130.9}]
expensive
## [{'name': 'AMZ', 'shares': 56, 'price': 1234.5}, {'name': 'GOOG', 'shares': 23, 'price': 678.4}, {'name': 'AAPL', 'shares': 40, 'price': 534.2}]

Implementing a priotity queue

You can use the heapq module to implement a queue that sorts items by their priority and returns the item with the highest priority, a priority queue.

class PriorityQueue:
  def __init__(self):
    self._queue = []
    self._index = 0
    
  def push(self, item, priority):
    heapq.heappush(self._queue, (-priority, self._index, item))
    self._index += 1
    
  def pop(self):
    return heapq.heappop(self._queue)[-1]

heapq.heappush and heapq.heappop insert and remove items from a queue. The priority is negated to sort the queue from highest to lowest.

We can create an item class to add items to a priority queue.

class Item:
  def __init__(self, name):
    self.name = name
  def __repr__(self):
    return f"Item({self.name})"
q = PriorityQueue()
q.push(Item("spoon"), 1)
q.push(Item("knife"), 3)
q.push(Item("fork"), 4)
q.push(Item("napkin"), 2)

Return (or rather extract) item with highest priority.

q.pop()
## Item(fork)
q.pop()
## Item(knife)
q.pop()
## Item(napkin)