Claude Code for heapq: Priority Queues in Python — Claude Skills 360 Blog
Blog / AI / Claude Code for heapq: Priority Queues in Python
AI

Claude Code for heapq: Priority Queues in Python

Published: July 21, 2028
Read time: 5 min read
By: Claude Skills 360

Python’s heapq module implements a min-heap on top of a plain list. import heapq. heappush: heapq.heappush(heap, item) — O(log n). heappop: heapq.heappop(heap) → smallest item, O(log n). heapify: heapq.heapify(lst) — in-place, O(n). heapreplace: heapq.heapreplace(heap, item) — pop and push, O(log n), more efficient than pop+push. heappushpop: heapq.heappushpop(heap, item) — push then pop, O(log n). nlargest: heapq.nlargest(n, iterable, key=...) — returns sorted list. nsmallest: heapq.nsmallest(n, iterable, key=...) — returns sorted list. merge: heapq.merge(*sorted_iterables, key=..., reverse=False) — lazy O(n log k). max-heap: negate values heapq.heappush(heap, -val). tuple heap: heapq.heappush(heap, (priority, item)) — compare on first element. tie-breaking: (priority, counter, item) — counter avoids comparing uncomparable items. peek: heap[0] — smallest without popping. empty check: while heap:. siftup/siftdown: internal functions, prefer public API. Heap invariant: heap[k] <= heap[2*k+1] and heap[k] <= heap[2*k+2]. Claude Code generates task schedulers, Dijkstra implementations, streaming top-N selectors, and event-driven simulation engines.

CLAUDE.md for heapq

## heapq Stack
- Stdlib: import heapq
- Push: heapq.heappush(heap, (priority, item))
- Pop:  priority, item = heapq.heappop(heap)
- Min:  heap[0]  — peek without removing
- Make: heapq.heapify(list)  — O(n) in-place
- Top-N: heapq.nlargest(10, items, key=lambda x: x.score)
- Max-heap: heapq.heappush(heap, -value)  — negate for max

heapq Priority Queue Pipeline

# app/heaputil.py — min-heap, max-heap, PriorityQueue, top-N, Dijkstra, median
from __future__ import annotations

import heapq
import itertools
from dataclasses import dataclass, field
from typing import Any, Callable, Generic, Iterable, Iterator, TypeVar

T  = TypeVar("T")
K  = TypeVar("K")


# ─────────────────────────────────────────────────────────────────────────────
# 1. Priority queue class
# ─────────────────────────────────────────────────────────────────────────────

class MinHeap(Generic[T]):
    """
    Min-priority queue with stable ordering on ties via an insertion counter.

    Example:
        pq = MinHeap[str]()
        pq.push("low-priority", priority=10)
        pq.push("high-priority", priority=1)
        _, task = pq.pop()   # "high-priority"
    """

    def __init__(self) -> None:
        self._heap:    list[tuple] = []
        self._counter: itertools.count = itertools.count()

    def push(self, item: T, priority: int | float = 0) -> None:
        """Push item with given priority (lower = higher urgency)."""
        heapq.heappush(self._heap, (priority, next(self._counter), item))

    def pop(self) -> tuple[int | float, T]:
        """Pop and return (priority, item) with the smallest priority."""
        priority, _, item = heapq.heappop(self._heap)
        return priority, item

    def peek(self) -> tuple[int | float, T] | None:
        """Return (priority, item) of the smallest item without removing it."""
        if not self._heap:
            return None
        priority, _, item = self._heap[0]
        return priority, item

    def __len__(self) -> int:
        return len(self._heap)

    def __bool__(self) -> bool:
        return bool(self._heap)


class MaxHeap(Generic[T]):
    """
    Max-priority queue (highest priority pops first) via negation.

    Example:
        pq = MaxHeap[str]()
        pq.push("job-a", priority=5)
        pq.push("job-b", priority=10)
        _, task = pq.pop()   # "job-b"
    """

    def __init__(self) -> None:
        self._heap:    list[tuple] = []
        self._counter: itertools.count = itertools.count()

    def push(self, item: T, priority: int | float = 0) -> None:
        heapq.heappush(self._heap, (-priority, next(self._counter), item))

    def pop(self) -> tuple[int | float, T]:
        neg_priority, _, item = heapq.heappop(self._heap)
        return -neg_priority, item

    def peek(self) -> tuple[int | float, T] | None:
        if not self._heap:
            return None
        neg_priority, _, item = self._heap[0]
        return -neg_priority, item

    def __len__(self) -> int:
        return len(self._heap)

    def __bool__(self) -> bool:
        return bool(self._heap)


# ─────────────────────────────────────────────────────────────────────────────
# 2. Top-N helpers
# ─────────────────────────────────────────────────────────────────────────────

def top_n(
    items: Iterable[T],
    n: int,
    key: Callable[[T], Any] = None,
    largest: bool = True,
) -> list[T]:
    """
    Return the n largest (or smallest) items efficiently.
    Uses sort for small n relative to data; O(n log n) otherwise.

    Example:
        scores = [{"name": "A", "score": 90}, {"name": "B", "score": 75}]
        top3 = top_n(scores, 3, key=lambda x: x["score"])
    """
    fn = heapq.nlargest if largest else heapq.nsmallest
    return fn(n, items, key=key)


def running_top_n(
    stream: Iterable[T],
    n: int,
    key: Callable[[T], Any] | None = None,
) -> list[T]:
    """
    Consume a stream, returning the top-n largest seen so far.
    O(total * log n) — maintains a window heap of size n.

    Example:
        result = running_top_n(log_entries, 5, key=lambda e: e.latency_ms)
    """
    heap: list = []
    _key = key or (lambda x: x)
    for item in stream:
        k = _key(item)
        if len(heap) < n:
            heapq.heappush(heap, (k, item))
        elif k > heap[0][0]:
            heapq.heapreplace(heap, (k, item))
    return [item for _, item in heapq.nlargest(n, heap)]


def merge_sorted(*iterables: Iterable[T], key: Callable[[T], Any] | None = None) -> Iterator[T]:
    """
    Lazily merge multiple sorted iterables in sorted order.

    Example:
        combined = list(merge_sorted([1, 3, 5], [2, 4, 6]))  # [1, 2, 3, 4, 5, 6]
    """
    return heapq.merge(*iterables, key=key)


# ─────────────────────────────────────────────────────────────────────────────
# 3. Running median (two-heap method)
# ─────────────────────────────────────────────────────────────────────────────

class RunningMedian:
    """
    Maintain an online running median using two heaps.
    Amortized O(log n) per insertion.

    Example:
        rm = RunningMedian()
        for v in [5, 3, 8, 1, 9, 2]:
            rm.add(v)
            print(rm.median)
    """

    def __init__(self) -> None:
        self._lo: list[float] = []   # max-heap (negated) — values ≤ median
        self._hi: list[float] = []   # min-heap — values ≥ median

    def add(self, value: float) -> None:
        heapq.heappush(self._lo, -value)
        # Balance: move lo's max to hi
        heapq.heappush(self._hi, -heapq.heappop(self._lo))
        # Keep lo at least as large as hi
        if len(self._lo) < len(self._hi):
            heapq.heappush(self._lo, -heapq.heappop(self._hi))

    @property
    def median(self) -> float:
        if not self._lo:
            raise ValueError("No values")
        if len(self._lo) > len(self._hi):
            return float(-self._lo[0])
        return (-self._lo[0] + self._hi[0]) / 2.0

    def __len__(self) -> int:
        return len(self._lo) + len(self._hi)


# ─────────────────────────────────────────────────────────────────────────────
# 4. Dijkstra shortest path
# ─────────────────────────────────────────────────────────────────────────────

def dijkstra(
    graph: dict[str, list[tuple[str, float]]],
    start: str,
    end: str | None = None,
) -> dict[str, float]:
    """
    Dijkstra's shortest-path algorithm using heapq.
    graph: {node: [(neighbor, weight), ...]}
    Returns distances from start to all reachable nodes.

    Example:
        graph = {
            "A": [("B", 1), ("C", 4)],
            "B": [("C", 2), ("D", 5)],
            "C": [("D", 1)],
            "D": [],
        }
        dist = dijkstra(graph, "A")
        print(dist["D"])   # 4.0
    """
    dist:    dict[str, float] = {}
    heap:    list[tuple[float, str]] = [(0.0, start)]

    while heap:
        d, node = heapq.heappop(heap)
        if node in dist:
            continue
        dist[node] = d
        if node == end:
            break
        for neighbor, weight in graph.get(node, []):
            if neighbor not in dist:
                heapq.heappush(heap, (d + weight, neighbor))

    return dist


def shortest_path(
    graph: dict[str, list[tuple[str, float]]],
    start: str,
    end: str,
) -> tuple[float, list[str]]:
    """
    Return (distance, path) for the shortest path from start to end.

    Example:
        dist, path = shortest_path(graph, "A", "D")
        print(f"{dist}: {' → '.join(path)}")
    """
    dist:   dict[str, float] = {}
    prev:   dict[str, str]   = {}
    heap:   list[tuple[float, str]] = [(0.0, start)]

    while heap:
        d, node = heapq.heappop(heap)
        if node in dist:
            continue
        dist[node] = d
        for neighbor, weight in graph.get(node, []):
            if neighbor not in dist:
                nd = d + weight
                if nd < dist.get(neighbor, float("inf")):
                    prev[neighbor] = node
                    heapq.heappush(heap, (nd, neighbor))

    # Reconstruct path
    path = []
    cur  = end
    while cur in prev:
        path.append(cur)
        cur = prev[cur]
    path.append(start)
    path.reverse()
    return dist.get(end, float("inf")), path


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=== heapq demo ===")

    print("\n--- MinHeap ---")
    pq: MinHeap[str] = MinHeap()
    for task, pri in [("low", 10), ("high", 1), ("medium", 5), ("urgent", 0)]:
        pq.push(task, priority=pri)
    print(f"  peek: {pq.peek()}")
    while pq:
        pri, task = pq.pop()
        print(f"  pop: {pri:3d}{task!r}")

    print("\n--- MaxHeap ---")
    mh: MaxHeap[str] = MaxHeap()
    for name, score in [("alice", 85), ("bob", 92), ("carol", 78)]:
        mh.push(name, priority=score)
    while mh:
        score, name = mh.pop()
        print(f"  {score}: {name}")

    print("\n--- top_n ---")
    data = [{"name": chr(65 + i), "score": (i * 37) % 100} for i in range(10)]
    top3 = top_n(data, 3, key=lambda x: x["score"])
    print(f"  top 3: {[(d['name'], d['score']) for d in top3]}")
    bot3 = top_n(data, 3, key=lambda x: x["score"], largest=False)
    print(f"  bot 3: {[(d['name'], d['score']) for d in bot3]}")

    print("\n--- running_top_n ---")
    result = running_top_n(range(1000), 5, key=lambda x: (x * 31) % 1000)
    print(f"  top 5 (hash): {result}")

    print("\n--- merge_sorted ---")
    merged = list(merge_sorted([1, 3, 5], [2, 4, 6], [0, 7, 8]))
    print(f"  {merged}")

    print("\n--- RunningMedian ---")
    rm = RunningMedian()
    for v in [5, 3, 8, 1, 9, 2, 7]:
        rm.add(v)
        print(f"  added {v:3d}  → median={rm.median}")

    print("\n--- dijkstra ---")
    graph = {
        "A": [("B", 1), ("C", 4)],
        "B": [("C", 2), ("D", 5)],
        "C": [("D", 1)],
        "D": [],
    }
    distances = dijkstra(graph, "A")
    print(f"  distances from A: {distances}")

    print("\n--- shortest_path ---")
    dist, path = shortest_path(graph, "A", "D")
    print(f"  A → D: {dist:.1f}  path: {' → '.join(path)}")

    print("\n=== done ===")

For the sortedcontainers.SortedList alternative — sortedcontainers.SortedList (PyPI) maintains sorted order for all insertions and supports O(log n) bisect_left/bisect_right and O(1) indexed access; heapq only guarantees O(1) access to the minimum, not arbitrary-rank access — use SortedList when you need sorted iteration, rank queries, or range slicing alongside insertions and deletions, heapq for pure priority-queue workloads (Dijkstra, simulation event queues) where only peek/pop-minimum matters. For the queue.PriorityQueue alternative — queue.PriorityQueue wraps heapq with thread-safe locking and a get(block=True, timeout=N) API, making it suitable for multi-threaded producer-consumer patterns; heapq is single-threaded only — use queue.PriorityQueue in multithreaded code where multiple threads push and pop jobs, heapq in single-threaded algorithms, async code (use asyncio.PriorityQueue), or when you need direct list access. The Claude Skills 360 bundle includes heapq skill sets covering MinHeap/MaxHeap generic classes with push/pop/peek, top_n()/running_top_n() top-N selectors with streaming support, merge_sorted() lazy sorted-merge, RunningMedian two-heap online median, and dijkstra()/shortest_path() graph shortest-path implementations. Start with the free tier to try priority queue patterns and heapq algorithm code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free