DotDict
DotDict
Section titled โDotDictโDotDict is a dictionary subclass that enables attribute-style access to dictionary keys. Instead of writing config["database"]["host"], you can write config.database.host. Nested plain dictionaries are automatically converted to DotDict instances on access, making the entire tree navigable with dot notation.
This utility is especially useful when working with configuration data, API responses, or any deeply nested dictionary structure where bracket notation becomes verbose and hard to read.
from orionis.support.wrapper.dot_dict import DotDictCreating an Instance
Section titled โCreating an InstanceโDotDict supports the same initialization signatures as a standard dict:
# From a dictionaryconfig = DotDict({"database": {"host": "localhost", "port": 5432}})
# From keyword argumentssettings = DotDict(debug=True, version="1.0")
# Empty instancedata = DotDict()Attribute Access
Section titled โAttribute AccessโReading Values
Section titled โReading ValuesโAccess dictionary keys as object attributes. Nested dictionaries are automatically wrapped in DotDict:
config = DotDict({ "app": { "name": "Orionis", "settings": { "debug": True } }})
config.app.name # "Orionis"config.app.settings.debug # TrueAccessing a key that does not exist returns None instead of raising an exception:
config = DotDict({"a": 1})config.missing_key # NoneSetting Values
Section titled โSetting ValuesโAssign values using attribute syntax. Plain dictionaries are automatically converted to DotDict:
config = DotDict()
config.name = "Orionis"config.database = {"host": "localhost", "port": 5432}
config.database.host # "localhost" โ auto-converted to DotDictDeleting Values
Section titled โDeleting ValuesโRemove keys using the del statement:
config = DotDict({"key": "value"})del config.keyRaises AttributeError if the key does not exist:
config = DotDict()del config.nonexistent # AttributeError: 'DotDict' has no attribute 'nonexistent'Methods
Section titled โMethodsโRetrieve a value by key with an optional default. Like attribute access, nested dicts are auto-converted:
config = DotDict({"timeout": 30, "retry": {"max": 3}})
config.get("timeout") # 30config.get("missing", 60) # 60config.get("missing") # Noneconfig.get("retry").max # 3Convert the entire DotDict tree back to standard Python dictionaries โ useful for serialization or passing data to libraries that expect plain dicts:
config = DotDict({"app": DotDict({"name": "Orionis", "meta": DotDict({"v": 1})})})
result = config.export()# {"app": {"name": "Orionis", "meta": {"v": 1}}}
type(result) # dict (not DotDict)type(result["app"]) # dict (not DotDict)Create a deep copy of the DotDict. Modifications to the copy do not affect the original:
original = DotDict({"nested": {"value": 10}})cloned = original.copy()
cloned.nested.value = 99original.nested.value # 10 โ unchangedStandard Dict Compatibility
Section titled โStandard Dict CompatibilityโDotDict inherits from dict, so all standard dictionary operations remain available:
config = DotDict({"a": 1, "b": 2, "c": 3})
# Bracket accessconfig["a"] # 1
# Membership test"a" in config # True"z" in config # False
# Iterationlist(config) # ["a", "b", "c"]
# Lengthlen(config) # 3
# Updateconfig.update({"d": 4})config.d # 4
# Reprrepr(config) # "{'a': 1, 'b': 2, 'c': 3, 'd': 4}"Deep Nesting
Section titled โDeep NestingโAttribute access works seamlessly through any number of nesting levels. All intermediate plain dicts are automatically converted and cached:
data = DotDict({ "level1": { "level2": { "level3": { "value": "deep" } } }})
data.level1.level2.level3.value # "deep"
# Mutation at any depthdata.level1.level2.level3.value = "modified"data.level1.level2.level3.value # "modified"Conversion Behavior
Section titled โConversion BehaviorโUnderstanding when and how plain dicts are converted to DotDict is key to using this class effectively:
| Operation | Plain dict auto-converted? | Cached in-place? |
|---|---|---|
d.key (attribute read) | Yes | Yes |
d.key = {...} (attribute write) | Yes | โ |
d.get("key") | Yes | Yes |
d["key"] (bracket read) | No | No |
d.copy() | Yes (deep) | โ |
d.export() | Reverse โ converts DotDict โ dict | โ |
Bracket-style access (d["key"]) does not auto-convert nested values. Use attribute access or get() when you need recursive DotDict behavior.