PYTHON

Implementing a Fixed-Size Circular Buffer (Ring Buffer)

Learn to implement a fixed-size circular buffer using a Python list, ideal for managing limited-history data or recent events in web applications while controlling memory usage.

class CircularBuffer:
    def __init__(self, capacity):
        if capacity <= 0:
            raise ValueError("Capacity must be greater than zero.")
        self.capacity = capacity
        self.buffer = [None] * capacity
        self.head = 0 # Points to the next write position
        self.size = 0 # Current number of elements in buffer

    def write(self, item):
        self.buffer[self.head] = item
        self.head = (self.head + 1) % self.capacity
        if self.size < self.capacity:
            self.size += 1

    def read(self):
        if self.size == 0:
            return None # Or raise an exception for empty buffer
        
        # The oldest item is at (head - size + capacity) % capacity
        read_index = (self.head - self.size + self.capacity) % self.capacity
        return self.buffer[read_index]
    
    def get_all(self):
        if self.size == 0:
            return []
        
        elements = []
        start_index = (self.head - self.size + self.capacity) % self.capacity
        for i in range(self.size):
            elements.append(self.buffer[(start_index + i) % self.capacity])
        return elements

    def is_empty(self):
        return self.size == 0
    
    def is_full(self):
        return self.size == self.capacity

    def __len__(self):
        return self.size

    def __str__(self):
        return f"CircularBuffer({self.get_all()}, head={self.head}, size={self.size}, capacity={self.capacity})"

# Example Usage:
buffer = CircularBuffer(3)
print(buffer.is_empty()) # True
buffer.write('Log 1')
buffer.write('Log 2')
print(buffer) # CircularBuffer(['Log 1', 'Log 2'], head=2, size=2, capacity=3)
buffer.write('Log 3')
print(buffer) # CircularBuffer(['Log 1', 'Log 2', 'Log 3'], head=0, size=3, capacity=3)
print(buffer.is_full()) # True
buffer.write('Log 4') # Overwrites 'Log 1'
print(buffer) # CircularBuffer(['Log 2', 'Log 3', 'Log 4'], head=1, size=3, capacity=3)
print(buffer.read()) # Output: 'Log 2'
print(buffer.get_all()) # Output: ['Log 2', 'Log 3', 'Log 4']
How it works: This snippet provides an implementation of a fixed-size circular buffer (also known as a ring buffer) using a Python list. This data structure is useful when you need to store a limited number of the most recent items, automatically overwriting the oldest items once the buffer is full. Common applications in web development include storing recent user actions, system logs, or a history of specific events without consuming excessive memory. The `head` pointer manages where the next item will be written, and modulo arithmetic (`% self.capacity`) ensures the buffer wraps around, effectively creating a circular storage mechanism.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs