heapq with custom compare predicate
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Python's heapq module does not accept a custom comparator or predicate argument. If you need custom ordering, the standard approach is to push values that already compare the way you want, usually tuples or small wrapper objects with a defined ordering.
Why There Is No Comparator Parameter
heapq works directly on Python objects and relies on their normal less-than comparison behavior. Unlike some other languages' priority queue APIs, it does not let you pass a comparison function such as cmp(a, b) or a predicate.
That means you solve custom priority by changing what goes into the heap, not by configuring the heap itself.
The Most Common Pattern: Store a Sort Key
If the ordering can be represented by a simple key, push a tuple where the first element is the priority.
Output comes out in ascending priority order because tuples compare element by element.
This is usually the best answer because it is simple, fast, and explicit.
Use a Tie-Breaker for Stability
If two items may share the same priority and the payload objects are not directly comparable, add a monotonic counter.
The counter ensures a stable and always-comparable second field, which avoids errors when Python tries to compare two dictionaries or other non-orderable objects.
Wrapper Objects with __lt__
If the ordering logic is more complex, wrap the data in a class and define __lt__.
This example makes higher importance values come out first, then uses earlier timestamp values as the tie-breaker.
A dataclass Version Can Be Cleaner
For simple wrappers, dataclasses can reduce boilerplate.
Fields with compare=False stay attached to the object without affecting heap order.
Max-Heap Behavior Is Usually Simulated
Because heapq is a min-heap, many "custom comparator" questions are really just max-heap questions. The simplest solution is to negate the numeric priority.
Negating the priority turns the smallest stored value into the largest logical priority.
Common Pitfalls
The most common mistake is looking for a comparator parameter that heapq simply does not have. Another is pushing tuples whose later elements are not comparable when priorities tie, which causes runtime errors during heap operations. Developers also implement complex __lt__ logic without making it consistent, which can lead to confusing ordering behavior. In many cases, a plain tuple key is simpler and safer than a custom class.
Summary
- '
heapqhas no custom comparator argument.' - Use tuples or wrapper objects whose natural ordering matches the desired priority.
- Add a tie-breaker counter when equal priorities are possible.
- Use
__lt__or ordered dataclasses for more complex ordering rules. - For max-heap behavior, negate the priority or otherwise invert the key.

