Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
234: The heapq Module for Priority Queues
Listen, I've seen this happen in dozens of code reviews: a developer wants a priority queue, they find the heapq module, and then they get frustrated because the list they're looking at doesn't look sorted. They'll say, "I pushed the items in, but the list is still a mess!"
The "It's Just a Sorted List" Trap
The biggest misconception about heapq is that it maintains a fully sorted list. It doesn't. If you push five numbers into a heap and then print the list, you'll likely see something that looks almost random. Let me show you exactly what I mean.
import heapq
tasks = []
heapq.heappush(tasks, 10)
heapq.heappush(tasks, 1)
heapq.heappush(tasks, 5)
print(tasks)
# You might expect [1, 5, 10], but you'll actually get [1, 10, 5]
At first glance, [1, 10, 5] looks wrong. But it's not. heapq implements a min-heap. The only absolute guarantee it gives you is that the smallest element is always at the front (index 0). The rest of the elements are arranged in a binary tree structure that makes it incredibly efficient to find the next smallest item, but it doesn't waste time sorting the entire list every time you add something.
The Min-Heap Reality
To actually get the elements in sorted order, you have to pop them. This is where the magic happens. When you call heappop(), Python removes the smallest item and then reshuffles the remaining elements just enough to ensure the new smallest item is back at index 0.
import heapq
# Let's use that same "messy" list from before
tasks = [1, 10, 5]
heapq.heapify(tasks) # Ensures the list satisfies the heap property
while tasks:
print(heapq.heappop(tasks))
# Output:
# 1
# 5
# 10
I usually tell my juniors to think of a heap as a "partially ordered" structure. It's a trade-off. Sorting a list takes O(N log N) time. Inserting into a heap only takes O(log N). If you only ever need the "best" or "smallest" item and don't care about the order of the rest, using a heap is significantly faster.
Handling Custom Priorities with Tuples
In the real world, you aren't just storing integers. You're storing objects—tasks, users, or packets. Since heapq sorts based on the first element of a tuple, the standard pattern is to store your data as (priority, data).
import heapq
# (Priority, Task Name) - Lower number means higher priority
queue = []
heapq.heappush(queue, (3, "Clean the kitchen"))
heapq.heappush(queue, (1, "Stop the server leak"))
heapq.heappush(queue, (2, "Email the client"))
while queue:
priority, task = heapq.heappop(queue)
print(f"Processing {task} (Priority: {priority})")
# Output:
# Processing Stop the server leak (Priority: 1)
# Processing Email the client (Priority: 2)
# Processing Clean the kitchen (Priority: 3)
One quick warning: if two items have the same priority, Python will try to compare the second element of the tuple (the task name in this case). If the second element is something that can't be compared (like a custom class instance), your code will crash. If that happens, I recommend adding a unique counter as a tie-breaker: (priority, count, task).
When to Use a Heap Over Sorting
You might be wondering, "Why not just call .sort() every time I add a task?" I've tried that in production—don't. If you have a list of 10,000 items and you add one new item, .sort() has to look at everything. A heap only has to perform a few swaps to move that new item into the correct relative position. Use heapq whenever you have a dynamic stream of data and you constantly need access to the minimum (or maximum) element.
📋 Practical Task
Building an Emergency Room Triage System
You need to build a triage system for a hospital. Patients arrive at different times with different urgency levels (1 being critical, 5 being non-urgent). You must ensure that the most critical patients are seen first, regardless of when they arrived.
Requirements:
- Create a list called
triage_queue. - Implement a function
add_patient(name, urgency)that pushes a tuple of(urgency, name)onto the heap. - Implement a function
treat_patient()that pops the highest priority patient from the heap and returns a string:"Treating [name]". If the queue is empty, return"No patients in queue".
Test Case:
add_patient("John Doe", 3)
add_patient("Jane Smith", 1)
add_patient("Bob Brown", 2)
print(treat_patient()) # Should be Jane Smith
print(treat_patient()) # Should be Bob Brown
There are no comments for now.