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.
Python code
49 linesclass 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
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
- Use a `dict` subclass that overrides methods directly, or wrap a `MutableMapping`.
- 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
More from Dictionaries & sets
- Build a defaultdict histogram of categories in Python easy
- Build adjacency dict graph from edges in Python easy
- Build an OrderedDict insertion order demo in Python 3 easy
- Check Invertible Mapping for Duplicate Values in Python easy
- Compare Two Dictionaries in Python easy
- Convert Lists and Dictionaries to Sets in Python easy
Keep learning
Related tutorials and quizzes for this topic.