Python module for interacting with nested dicts as a single level dict with delimited keys.
npx @tessl/cli install tessl/pypi-flatdict@4.0.0Python module for interacting with nested dicts as a single level dict with delimited keys. FlatDict allows access to deeply nested values using composite keys (e.g., 'foo:bar:baz') while maintaining compatibility with standard dictionary operations through the MutableMapping interface.
pip install flatdictimport flatdictFor direct class access:
from flatdict import FlatDict, FlatterDictimport flatdict
# Create a FlatDict from nested dictionary
nested_data = {
'foo': {
'bar': 'baz',
'qux': 'corge'
},
'grault': {
'garply': 'waldo'
}
}
# FlatDict flattens nested structures
flat = flatdict.FlatDict(nested_data)
# Access using composite keys with delimiter (default ':')
print(flat['foo:bar']) # 'baz'
print(flat['foo:qux']) # 'corge'
print(flat['grault:garply']) # 'waldo'
# Also supports traditional dictionary access
print(flat['foo']['bar']) # 'baz'
# Iterate over flattened keys
for key in flat.keys():
print(f"{key}: {flat[key]}")
# Convert back to nested dictionary
nested = flat.as_dict()FlatDict implements Python's MutableMapping abstract base class, providing a complete dictionary interface while internally managing nested data structures. The key innovation is the flattening mechanism that converts nested dictionaries into single-level dictionaries using delimited keys.
Core Design:
This approach allows intuitive access to deeply nested data while maintaining the familiar dictionary API that Python developers expect.
Main dictionary class that flattens nested dictionaries into single-level dictionaries with delimited keys. Implements the MutableMapping interface for full dictionary compatibility.
class FlatDict:
def __init__(self, value=None, delimiter=':', dict_class=dict):
"""
Initialize FlatDict.
Parameters:
- value: dict or None, initial nested dictionary to flatten
- delimiter: str, character to use for key separation (default ':')
- dict_class: type, dictionary class to use internally (default dict)
"""
def __contains__(self, key):
"""Check if key exists, supporting both delimited and non-delimited keys."""
def __delitem__(self, key):
"""Delete item by key, automatically handling nested children."""
def __eq__(self, other):
"""Check equality against dict or FlatDict."""
def __ne__(self, other):
"""Check inequality against dict or FlatDict."""
def __getitem__(self, key):
"""Get item by key, supporting delimited key access."""
def __iter__(self):
"""Iterate over flattened keys."""
def __len__(self):
"""Return number of flattened items."""
def __setitem__(self, key, value):
"""Set item by key, supporting delimited key assignment."""
def __str__(self):
"""String representation of flattened dictionary."""
def __repr__(self):
"""Detailed string representation."""
def __reduce__(self):
"""
Return state information for pickling.
Returns:
tuple: State information for pickle reconstruction
"""
def as_dict(self):
"""
Convert FlatDict back to nested dictionary.
Returns:
dict: Nested dictionary representation
"""
def clear(self):
"""Remove all items from the flat dictionary."""
def copy(self):
"""
Return shallow copy of the flat dictionary.
Returns:
FlatDict: Copy with same delimiter
"""
def get(self, key, d=None):
"""
Get item with default value.
Parameters:
- key: Key to lookup
- d: Default value if key not found
Returns:
Value at key or default
"""
def items(self):
"""
Return list of (key, value) pairs.
Returns:
list: Flattened key-value pairs
"""
def iteritems(self):
"""Iterator over (key, value) pairs."""
def iterkeys(self):
"""Iterator over flattened keys."""
def itervalues(self):
"""Iterator over values."""
def keys(self):
"""
Return list of flattened keys.
Returns:
list: All flattened keys with delimiters
"""
def pop(self, key, default=None):
"""
Remove and return item.
Parameters:
- key: Key to remove
- default: Value to return if key not found (optional)
Returns:
Value that was removed or default
Raises:
KeyError: If key not found and no default provided
"""
def setdefault(self, key, default):
"""
Get item or set and return default.
Parameters:
- key: Key to check/set
- default: Value to set if key doesn't exist
Returns:
Value at key or default that was set
"""
def set_delimiter(self, delimiter):
"""
Change the delimiter character.
Parameters:
- delimiter: str, new delimiter character
Raises:
ValueError: If delimiter conflicts with existing keys
"""
def update(self, other=None, **kwargs):
"""
Update with key/value pairs from other dict or kwargs.
Parameters:
- other: dict-like object or iterable of key/value pairs
- **kwargs: Additional key/value pairs
"""
def values(self):
"""
Return list of values.
Returns:
list: All values in the flattened dictionary
"""Extended version of FlatDict that also handles lists, tuples, and sets by converting them to dictionary structures using enumeration. Maintains original type information for reconstruction.
class FlatterDict(FlatDict):
def __init__(self, value=None, delimiter=':', dict_class=dict):
"""
Initialize FlatterDict with array coercion.
Parameters:
- value: dict, list, tuple, set, or None - initial data structure
- delimiter: str, character for key separation (default ':')
- dict_class: type, dictionary class to use internally (default dict)
Attributes:
- original_type: type, stores the original type of the input value
Class Constants:
- _COERCE: tuple, types that get coerced to FlatterDict (list, tuple, set, dict, FlatDict)
- _ARRAYS: tuple, array types that get special handling (list, set, tuple)
"""
def __setitem__(self, key, value):
"""Enhanced setitem that handles arrays (list, tuple, set)."""
def as_dict(self):
"""
Convert FlatterDict back to nested structure preserving original types.
Returns:
dict: Nested structure with original array types restored
"""__version__: str # Package version string
NO_DEFAULT: object # Sentinel object for internal use# FlatDict class constants
FlatDict._COERCE = dict # Types that get coerced to FlatDict
# FlatterDict class constants
FlatterDict._COERCE = (list, tuple, set, dict, FlatDict) # Types coerced to FlatterDict
FlatterDict._ARRAYS = (list, set, tuple) # Array types with special handlingThe flatdict module raises standard Python exceptions:
__getitem__, __delitem__, or pop() without defaultset_delimiter() when the new delimiter conflicts with existing keys# Use different delimiter
flat = flatdict.FlatDict({'a': {'b': 'c'}}, delimiter='.')
print(flat['a.b']) # 'c'
# Change delimiter after creation
flat.set_delimiter('/')
print(flat['a/b']) # 'c'# FlatterDict handles lists, tuples, and sets
data = {
'items': ['a', 'b', 'c'],
'coords': (1, 2, 3),
'tags': {'red', 'blue', 'green'}
}
flatter = flatdict.FlatterDict(data)
# Access array elements by index
print(flatter['items:0']) # 'a'
print(flatter['coords:1']) # 2
# Convert back preserving original types
restored = flatter.as_dict()
print(type(restored['items'])) # <class 'list'>
print(type(restored['coords'])) # <class 'tuple'>
print(type(restored['tags'])) # <class 'set'>flat = flatdict.FlatDict({'a': {'b': 1, 'c': 2}})
# Standard dictionary operations work
len(flat) # 2
'a:b' in flat # True
list(flat) # ['a:b', 'a:c']
# Update with nested data
flat.update({'d': {'e': 3}})
print(flat['d:e']) # 3
# Copy preserves delimiter
flat2 = flat.copy()