Python Queue: Understanding FIFO and LIFO with Examples
Introduction
Queues are fundamental data structures used in computer science to manage and organize elements in a specific order. Python provides a versatile queue
module that includes implementations of different types of queues. In this comprehensive blog post, we’ll explore the concepts of FIFO (First-In-First-Out) and LIFO (Last-In-First-Out) queues, delve into the Python queue
module, and showcase examples to illustrate their usage in various scenarios.
Understanding FIFO and LIFO
FIFO (First-In-First-Out): In a FIFO queue, the first element added is the first to be removed. It follows the principle of “first come, first served.” Imagine a line of people waiting for a bus—the person who arrives first gets on the bus first.
LIFO (Last-In-First-Out): In a LIFO queue, the last element added is the first to be removed. It follows the principle of “last come, first served.” Think of a stack of plates—the plate added last is the first one you can remove.
Python queue
Module
Python’s queue
module provides several classes that implement different types of queues. Two prominent classes are Queue
and LifoQueue
, representing FIFO and LIFO queues, respectively. Let’s explore their usage with examples.
Example 1: FIFO Queue (Queue Class)
import queue
# Creating a FIFO queue
fifo_queue = queue.Queue()
# Enqueue elements
fifo_queue.put(1)
fifo_queue.put(2)
fifo_queue.put(3)
# Dequeue elements
print(fifo_queue.get()) # Output: 1
print(fifo_queue.get()) # Output: 2
Example 2: LIFO Queue (LifoQueue Class)
import queue
# Creating a LIFO queue
lifo_queue = queue.LifoQueue()
# Push elements
lifo_queue.put(1)
lifo_queue.put(2)
lifo_queue.put(3)
# Pop elements
print(lifo_queue.get()) # Output: 3
print(lifo_queue.get()) # Output: 2
In these examples, we create a FIFO queue using queue.Queue()
and a LIFO queue using queue.LifoQueue()
. The put()
method is used to enqueue elements, and the get()
method is used to dequeue elements.
Practical Examples
Example 3: Task Processing with a FIFO Queue
Consider a scenario where tasks need to be processed in the order they are received. A FIFO queue is an excellent choice for this:
import queue
import threading
import time
def process_task(task_queue):
while True:
task = task_queue.get()
# Process the task (simulated by printing)
print(f"Processing task: {task}")
# Simulating task processing time
time.sleep(1)
task_queue.task_done()
# Creating a FIFO queue for tasks
task_queue = queue.Queue()
# Creating worker threads for task processing
for _ in range(3):
worker = threading.Thread(target=process_task, args=(task_queue,))
worker.daemon = True
worker.start()
# Enqueue tasks
for task_id in range(5):
task_queue.put(task_id)
# Wait for all tasks to be processed
task_queue.join()
In this example, tasks are enqueued in a FIFO queue, and worker threads process the tasks in the order they are received.
Example 4: Managing a Stack of Undo Actions with a LIFO Queue
Suppose you are implementing an application with an undo feature. A LIFO queue can be used to manage the stack of undo actions:
import queue
class UndoManager:
def __init__(self):
self.undo_stack = queue.LifoQueue()
def do_action(self, action):
# Perform the action (simulated by printing)
print(f"Doing action: {action}")
# Push the action to the undo stack
self.undo_stack.put(action)
def undo_last_action(self):
if not self.undo_stack.empty():
# Pop the last action from the undo stack
last_action = self.undo_stack.get()
# Undo the action (simulated by printing)
print(f"Undoing action: {last_action}")
# Example usage
undo_manager = UndoManager()
undo_manager.do_action("Edit Text")
undo_manager.do_action("Insert Image")
undo_manager.do_action("Format Document")
# Performing undo
undo_manager.undo_last_action()
undo_manager.undo_last_action()
In this example, the UndoManager
class manages a LIFO queue (undo_stack
) to keep track of actions for undoing.
Conclusion
Understanding and utilizing FIFO and LIFO queues in Python, as provided by the queue
module, empowers developers to implement efficient and organized data processing. Whether managing tasks in a threaded environment, implementing undo features, or handling any scenario where the order of operations matters, FIFO and LIFO queues offer valuable solutions. By exploring the examples presented in this blog post, Python developers can integrate these queue concepts into their projects and enhance the robustness and efficiency of their applications.