How to Build an In-Memory CRUD Repository Class in Python

Define a Python Repository class that stores objects in a dictionary and supports create, read, update, delete, and list operations.

Easy Python 3.9+ Aug 9, 2026 OOP & classes 14 views 0 copies

Python code

40 lines
Python 3.9+
class Repository:
    def __init__(self):
        self._data = {}

    def create(self, key, value):
        self._data[key] = value
        return key

    def read(self, key):
        return self._data.get(key)

    def update(self, key, value):
        if key not in self._data:
            raise KeyError(f"Key '{key}' not found")
        self._data[key] = value
        return value

    def delete(self, key):
        if key not in self._data:
            raise KeyError(f"Key '{key}' not found")
        return self._data.pop(key)

    def list_all(self):
        return list(self._data.items())


if __name__ == "__main__":
    repo = Repository()

    repo.create("user1", {"name": "Alice", "age": 30})
    repo.create("user2", {"name": "Bob", "age": 25})

    print(f"Initial: {repo.list_all()}")
    print(f"Read user1: {repo.read('user1')}")
    
    repo.update("user2", {"name": "Robert", "age": 26})
    print(f"After update: {repo.list_all()}")
    
    repo.delete("user1")
    print(f"After delete: {repo.list_all()}")

Output

stdout
Initial: [('user1', {'name': 'Alice', 'age': 30}), ('user2', {'name': 'Bob', 'age': 25})]
Read user1: {'name': 'Alice', 'age': 30}
After update: [('user1', {'name': 'Alice', 'age': 30}), ('user2', {'name': 'Robert', 'age': 26})]
After delete: [('user2', {'name': 'Robert', 'age': 26})]

How it works

The Repository class wraps a private dictionary _data to manage entries. The create method simply assigns a value to a key and returns the key. read uses dict.get to return None when the key is missing, avoiding a KeyError. update and delete raise a KeyError explicitly if the key does not exist, making invalid operations loud. list_all returns a list of key-value tuples, giving a snapshot of all data. Because all state lives on self, you can have multiple independent repositories without global variables.

Common mistakes

  • Using `read` with direct indexing `self._data[key]` raises KeyError for missing keys; prefer `.get` for safe reads.
  • Forgetting to check key existence in `update` or `delete`, leading to silent errors or unexpected behavior.
  • Storing mutable objects and modifying them in place can cause side effects; consider returning copies if isolation is needed.

Variations

  1. Add a `clear` method to reset the repository.
  2. Use `defaultdict` to automatically create entries on read for certain patterns.

Real-world use cases

  • Acting as a lightweight in-memory cache for frequently accessed configuration or session data in a small application.
  • Serving as a stub store in unit tests when you want to isolate code that would otherwise hit a database.
  • Powering a simple in-memory key-value store for a prototype or local development tool before wiring up a real datastore.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from OOP & classes

Related tutorials and quizzes for this topic.