Python Queue: Understanding FIFO and LIFO with Examples

Created with Sketch.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *