Reputation: 949
What I am looking for is having something like this:
self.info['key'].attr2
But I'm not sure what would be the most elegant way to achieve it. So far I have defined a dictionary like below but don't have attributes from it.
self.info = {}
self.info.update({'key':
{'attr1': 2,
'attr2': lambda: self.func(arg1)}
})
But then I would have to use it like:
self.info['key']['attr2']()
Note that what I am looking for is accessing the dictionary values like attributes. This thread has an answer which can be used in my case also probably that is I make an object out of the sub-dictionary from above and give it as a value to the main dictionary.
But I wonder if there is nicer way, perhaps with decorators and with less lines of codes and maybe even without using dictionaries do to something like what I described in the first line, perhaps even better like:
self['key'].attr2
Upvotes: 8
Views: 4841
Reputation: 678
There's a library for that called Box. Very convenient. https://pypi.org/project/python-box/
It handles all kinds of edge cases, like dictionaries inside dictionaries and lists etc.
pip install python-box
from box import Box
movie_box = Box({
"Robin Hood: Men in Tights": {
"imdb_stars": 6.7,
"length": 104,
"stars": [ {"name": "Cary Elwes", "imdb": "nm0000144", "role": "Robin Hood"},
{"name": "Richard Lewis", "imdb": "nm0507659", "role": "Prince John"} ]
}
})
movie_box.Robin_Hood_Men_in_Tights.imdb_stars
# 6.7
movie_box.Robin_Hood_Men_in_Tights.stars[0].name
# 'Cary Elwes'
Upvotes: 0
Reputation: 3734
Here is a short wrapper to access dict keys as attributes:
class nameddict(dict):
__getattr__ = dict.__getitem__
info = nameddict()
info['key'] = nameddict(attr1=2, attr2=3)
Then info['key'].attr2
as well as info['key']['attr2']
and info.key.attr2
returns 3
.
Upvotes: 9
Reputation: 5735
if you want a more dynamic container for which you don't need to declare the attributes like in namedtuple you can use SimpleNamespace object.
from types import SimpleNamespace as ns
info = {}
info.update({'key': ns(attr1=2, attr2=lambda x: x+1)})
Upvotes: 4
Reputation: 4461
You could use collections.namedtuple
, as suggested in the thread you link:
Attrs = namedtuple("Attrs", ["attr1", "attr2"])
info = {"key": Attrs(attr1=2, attr2=lambda: 4)}
info["key"].attr2()
Upvotes: 2