ZetCode

Python __delitem__ Method

Last modified April 8, 2025

This comprehensive guide explores Python's __delitem__ method, the special method responsible for item deletion in container objects. We'll cover basic usage, dictionary operations, list operations, and custom implementations.

Basic Definitions

The __delitem__ method is called to implement deletion of items using the del statement or similar operations. It allows objects to define custom behavior when items are deleted by key or index.

Key characteristics: it takes the instance (self) and key/index as arguments, modifies the object in-place, and typically returns None. It's invoked by del obj[key] syntax.

Basic __delitem__ Implementation

Here's a simple implementation showing how __delitem__ works in a custom container class. This demonstrates the basic structure and usage.

basic_delitem.py
class MyContainer:
    def __init__(self):
        self.data = {'a': 1, 'b': 2, 'c': 3}
    
    def __delitem__(self, key):
        print(f"Deleting item with key: {key}")
        del self.data[key]

container = MyContainer()
del container['b']  # Calls __delitem__
print(container.data)  # {'a': 1, 'c': 3}

This example shows a container that wraps a dictionary. When we use del on an item, it calls __delitem__ which then deletes from the internal dictionary.

The method receives the key used in the deletion operation and performs the actual removal from the container's storage. No return value is needed.

Implementing List-like Deletion

For sequence types that support index-based deletion, __delitem__ can handle both integers and slices, similar to built-in lists.

list_delitem.py
class MyList:
    def __init__(self, items):
        self.items = list(items)
    
    def __delitem__(self, index):
        if isinstance(index, slice):
            del self.items[index]
        else:
            del self.items[index]
    
    def __repr__(self):
        return f"MyList({self.items})"

lst = MyList([10, 20, 30, 40, 50])
del lst[1]      # Delete single item
print(lst)      # MyList([10, 30, 40, 50])
del lst[1:3]    # Delete slice
print(lst)      # MyList([10, 50])

This list-like class handles both single index deletion and slice deletion. The method checks the type of the index parameter to handle both cases properly.

The slice handling is identical to Python's built-in list behavior, making the class behave like a standard sequence type.

Dictionary Subclass with Deletion Logging

We can create a dictionary subclass that logs all deletion operations by overriding __delitem__ while maintaining all dictionary behavior.

logging_dict.py
class LoggingDict(dict):
    def __delitem__(self, key):
        print(f"Log: Deleting key '{key}'")
        super().__delitem__(key)

d = LoggingDict({'red': '#FF0000', 'green': '#00FF00', 'blue': '#0000FF'})
del d['green']  # Logs the deletion
print(d)        # {'red': '#FF0000', 'blue': '#0000FF'}

This dictionary subclass adds logging before performing the actual deletion. It uses super() to call the parent class's __delitem__.

This pattern is useful for debugging or tracking changes in dictionary-like objects without changing their core functionality.

Custom Container with Deletion Constraints

__delitem__ can enforce constraints on what items can be deleted, such as preventing deletion of certain protected keys.

protected_container.py
class ProtectedContainer:
    def __init__(self):
        self._data = {'config': {}, 'values': {}}
        self._protected = {'config'}
    
    def __delitem__(self, key):
        if key in self._protected:
            raise KeyError(f"Cannot delete protected key: {key}")
        del self._data[key]
    
    def __repr__(self):
        return str(self._data)

pc = ProtectedContainer()
pc._data['config']['timeout'] = 30
pc._data['values']['temp'] = 98.6

try:
    del pc['config']  # Raises KeyError
except KeyError as e:
    print(e)

del pc['values']  # Works
print(pc)  # {'config': {'timeout': 30}}

This container protects certain keys from deletion by checking against a set of protected keys before allowing the operation. It raises KeyError for protected items.

This pattern is useful when you need to maintain certain internal state while allowing modification of other parts of the container.

Matrix Class with Row/Column Deletion

For more complex data structures, __delitem__ can implement sophisticated deletion logic, like removing entire rows or columns from a matrix.

matrix_deletion.py
class Matrix:
    def __init__(self, rows, cols):
        self.rows = [[0] * cols for _ in range(rows)]
        self.row_count = rows
        self.col_count = cols
    
    def __delitem__(self, key):
        if isinstance(key, tuple) and len(key) == 2:
            row, col = key
            self.rows[row][col] = 0
        elif isinstance(key, int):
            del self.rows[key]
            self.row_count -= 1
        else:
            raise TypeError("Invalid key type")
    
    def __repr__(self):
        return '\n'.join(' '.join(map(str, row)) for row in self.rows)

m = Matrix(3, 3)
m.rows = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print("Original matrix:")
print(m)

del m[1]  # Delete entire row
print("\nAfter deleting row 1:")
print(m)

del m[0, 1]  # Delete single element (set to 0)
print("\nAfter deleting element at (0,1):")
print(m)

This matrix class handles two types of deletion: removing entire rows (by integer index) or zeroing out individual elements (by (row,col) tuple). The method checks the key type to determine the operation.

This demonstrates how __delitem__ can support multiple deletion semantics in a single class, providing flexible container behavior.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.