Build a Case-Insensitive Dict with a Wrapper Class in Python

Create a custom dict subclass that treats keys as case-insensitive by normalizing them to lowercase, with a full set of common dict methods.

Medium Python 3.9+ Aug 9, 2026 Dictionaries & sets 13 views 0 copies

Python code

49 lines
Python 3.9+
class CaseInsensitiveDict:
    def __init__(self, data=None):
        self._data = {}
        if data:
            self.update(data)

    def __setitem__(self, key, value):
        self._data[str(key).lower()] = value

    def __getitem__(self, key):
        return self._data[str(key).lower()]

    def __delitem__(self, key):
        del self._data[str(key).lower()]

    def __contains__(self, key):
        return str(key).lower() in self._data

    def __len__(self):
        return len(self._data)

    def __iter__(self):
        return iter(self._data)

    def update(self, data):
        if isinstance(data, dict):
            for key, value in data.items():
                self[key] = value
        else:
            for key, value in data:
                self[key] = value

    def get(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            return default

    def __str__(self):
        return str(self._data)


if __name__ == "__main__":
    cin = CaseInsensitiveDict({"Name": "Alice", "AGE": 30})
    print(cin["name"])
    print(cin.get("age"))
    print("AGE" in cin)
    cin["City"] = "New York"
    print(cin)

Output

stdout
Alice
30
True
{'name': 'Alice', 'age': 30, 'city': 'New York'}

How it works

This wrapper class stores keys in lowercase internally while exposing normal dict-like behavior. The __setitem__ and __getitem__ methods convert the key to lowercase before delegating to the internal _data dict. The get method safely falls back to a default instead of raising. Iteration and len work as expected because they delegate to the internal dict. This pattern is useful for handling user input where key casing is inconsistent.

Common mistakes

  • Forgetting to convert keys to lowercase in both get and set methods
  • Not converting keys on `in` checks, causing false negatives
  • Assuming the internal `_data` is accessible directly — always go through the wrapper

Variations

  1. Use a `dict` subclass that overrides methods directly, or wrap a `MutableMapping`.
  2. Store original casing separately if needed for output fidelity.

Real-world use cases

  • Normalizing HTTP headers in web frameworks like Flask or Django where header names are case-insensitive.
  • Handling user configuration files where keys may be typed with different casing across versions.
  • Parsing query strings or form data where users may use mixed-case parameter names.

Sponsored

Run this sample

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

Open editor

More from Dictionaries & sets

Related tutorials and quizzes for this topic.