Method 1: Get dictionary keys as a list using dict. The dict. keys() method in Python Dictionary, returns a view object that displays a list of all the keys in the dictionary in order of insertion.
A special attribute of every module is __dict__. This is the dictionary containing the module's symbol table. object.__dict__ A dictionary or other mapping object used to store an object's (writable) attributes.
The DotDict class is a subclass of a standard Python dict that provides access to its keys as attributes. This object is used mainly for parsed XML content returned by MWSResponse. parsed and MWSResponse. metadata , but DotDict can also be used as a general-purpose dict replacement (with some caveats, as shown below).
It's precisely because Python is all about readability that there is no dotted access for dict keys.
Here's one way to create that kind of experience:
class DotDictify(dict):
MARKER = object()
def __init__(self, value=None):
if value is None:
pass
elif isinstance(value, dict):
for key in value:
self.__setitem__(key, value[key])
else:
raise TypeError('expected dict')
def __setitem__(self, key, value):
if isinstance(value, dict) and not isinstance(value, DotDictify):
value = DotDictify(value)
super(DotDictify, self).__setitem__(key, value)
def __getitem__(self, key):
found = self.get(key, DotDictify.MARKER)
if found is DotDictify.MARKER:
found = DotDictify()
super(DotDictify, self).__setitem__(key, found)
return found
__setattr__, __getattr__ = __setitem__, __getitem__
if __name__ == '__main__':
life = {'bigBang':
{'stars':
{'planets': {} # Value changed from []
}
}
}
life = DotDictify(life)
print(life.bigBang.stars.planets) # -> []
life.bigBang.stars.planets.earth = {'singleCellLife' : {}}
print(life.bigBang.stars.planets) # -> {'earth': {'singleCellLife': {}}}
Below another implementation of a nested attribute dictionary (inspired by the answer of Curt Hagenlocher, stripped down to the essential):
class AttrDict(dict):
""" Nested Attribute Dictionary
A class to convert a nested Dictionary into an object with key-values
accessible using attribute notation (AttrDict.attribute) in addition to
key notation (Dict["key"]). This class recursively sets Dicts to objects,
allowing you to recurse into nested dicts (like: AttrDict.attr.attr)
"""
def __init__(self, mapping=None):
super(AttrDict, self).__init__()
if mapping is not None:
for key, value in mapping.items():
self.__setitem__(key, value)
def __setitem__(self, key, value):
if isinstance(value, dict):
value = AttrDict(value)
super(AttrDict, self).__setitem__(key, value)
self.__dict__[key] = value # for code completion in editors
def __getattr__(self, item):
try:
return self.__getitem__(item)
except KeyError:
raise AttributeError(item)
__setattr__ = __setitem__
This works in both Python 2 and 3:
life = AttrDict({'bigBang': {'stars': {'planets': {}}}})
life['bigBang']['stars']['planets'] = {'earth': {'singleCellLife': {}}}
life.bigBang.stars.planets.earth.multiCellLife = {'reptiles': {}, 'mammals': {}}
print(life.bigBang.stars.planets.earth)
# -> {'singleCellLife': {}, 'multiCellLife': {'mammals': {}, 'reptiles': {}}}
Converting KeyError into AttributeError in __getattr__
is required in Python3 such that hasattr
works also in case the attribute is not found:
hasattr(life, 'parallelUniverse')
# --> False
There is a package doing exactly what you want and also something more and it is called Prodict.
from prodict import Prodict
life_dict = {'bigBang':
{'stars':
{'planets': []}
}
}
life = Prodict.from_dict(life_dict)
print(life.bigBang.stars.planets)
# prints []
# you can even add new properties dynamically
life.bigBang.galaxies = []
PS: I'm the author of the Prodict.
Here is another solution:
from typing import Dict, Any
class PropertyTree: pass
def dict_to_prop_tree(yaml_config: Dict[str, Any]) -> PropertyTree:
tree = PropertyTree()
for key, value in yaml_config.items():
if type(value) == dict:
setattr(tree, key, dict_to_obj_tree(value))
elif type(value) == list:
setattr(tree, key, [dict_to_obj_tree(v) for v in value])
else:
setattr(tree, key, value)
return tree
Then in the python console:
d={'a': 1, 'b': 2, 'c': {'d': 4, 'e': 5, 'f': {'g': 6}, 'h': {}, 'j': 7}}
tree=dict_to_prop_tree(d)
tree.a
tree.c.f.g
prints the correct values
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With