Altcademy - a Forbes magazine logo Best Coding Bootcamp 2023

what built in Python data type is best suited for implementing a queue

Understanding Queues in Programming

Imagine you're waiting in line to buy the latest smartphone. The first person in line gets served first, and as they leave, the next person steps up. This is exactly how a queue works. It's a collection where items are added at one end and removed from the other, following the principle of "first in, first out" (FIFO). In other words, the first element added to the queue will be the first one to be removed.

Python Data Types and the Queue

In Python, there are several built-in data types that you could use to implement a queue. The most commonly used are lists, deque (from the collections module), and the queue.Queue class from the queue module. We'll explore each of these options, providing examples and explaining which is best suited for a queue implementation.

Using Lists as Queues

A list in Python is a dynamic array that can grow or shrink in size. You can add elements to the end of a list using the append() method, and you can remove elements from the beginning using the pop(0) method. Here's an example of a queue using a list:

# Initialize an empty list as a queue
queue = []

# Add elements to the queue
queue.append('John')
queue.append('Jane')
queue.append('Alice')

# Remove an element from the queue
served_customer = queue.pop(0)
print(served_customer)  # Output: John

However, using lists as queues is not efficient. When you pop(0), Python has to shift all the other elements one position to the left. This is a time-consuming operation, especially if the list is long.

The deque Data Type

The deque (pronounced "deck"), which stands for "double-ended queue," is a data type from the collections module specifically designed to have fast appends and pops from both ends. It's perfect for queue operations because it's optimized for these tasks. Here's how you can use a deque as a queue:

from collections import deque

# Initialize a deque as a queue
queue = deque()

# Add elements to the queue
queue.append('John')
queue.append('Jane')
queue.append('Alice')

# Remove an element from the queue
served_customer = queue.popleft()
print(served_customer)  # Output: John

Notice the use of the popleft() method, which removes and returns the leftmost element of the deque, which is the first element that was added—exactly what we need for a queue.

The queue.Queue Class

Python also has a queue module, which provides the Queue class. This class is designed for thread-safe queues, which means it can be used in programs where multiple threads (think of them as separate, smaller programs that can run at the same time within a larger program) might be adding or removing elements from the queue simultaneously. Here's an example:

from queue import Queue

# Initialize a Queue
queue = Queue()

# Add elements to the queue
queue.put('John')
queue.put('Jane')
queue.put('Alice')

# Remove an element from the queue
served_customer = queue.get()
print(served_customer)  # Output: John

The Queue class is a great choice if you're working with threads, but it's a bit more heavyweight than deque for a simple queue implementation.

Which One to Use?

For most applications, the deque from the collections module is the best choice for implementing a queue in Python. It's efficient and straightforward to use. The list is not suitable due to performance issues, and the Queue class is overkill unless you need thread safety.

Practical Example: A Print Queue

Let's imagine you're building a simple program to manage a print queue for an office printer. Here's how you might use a deque to do this:

from collections import deque

# Initialize the print queue
print_queue = deque()

# Users add print jobs to the queue
print_queue.append('Document1.pdf')
print_queue.append('Document2.pdf')
print_queue.append('Image1.png')

# The printer starts printing and removing jobs from the queue
while print_queue:
    current_job = print_queue.popleft()
    print(f"Printing {current_job}")
    # Simulate the time it takes to print
    # time.sleep(5)

In this example, documents are added to the queue in the order they're received. The printer then processes each job in turn, starting with the first one added to the queue.

Conclusion

Queues are a fundamental concept in programming, resembling a real-world line. In Python, while you have several options to implement a queue, the deque stands out for its efficiency and simplicity. It's like having a dedicated lane for express service in our earlier analogy of a line for buying a smartphone. By choosing the right data type, you can ensure that your virtual line moves quickly and efficiently, keeping your program running smoothly. Whether you're managing print jobs or creating a task scheduler, remember that the humble deque is often the unsung hero of data structures, keeping your data in order and your processes in check.