Reputation: 454
I have the following info structure:
items= {i1: {ref: i1_ref, attrs: {attr1: 'red', attr2: 'low'}}, i2: {ref: i2_def, attrs: {attr1: 'green', attr2: 'hight'}}}
i1
, i2
... are strings.
i1_ref
, i2_ref
... are strings also.
I would like have an object i
to be able to retrieve the information as follows:
i.i1
to get the ref from i1 (i1_ref value), i.i2
to get the ref from i2 (i2_ref value).i.i1.attrs
to get the nested dictionary of attributes from i1,i.i2.attrs
to get the nested dictionary of attributes from i2.Code:
print(i.i1)
>>> i1_ref
print(i.i1.attrs)
>>> {attr1: 'red', attr2: 'low'}
Upvotes: 1
Views: 512
Reputation: 2569
A solution that adds attributes to a subclass of str
to get the desired behavior.
items = {
"i1": {"ref": "i1_ref", "attrs": {"attr1": 'red', "attr2": 'low'}},
"i2": {"ref": "i2_def", "attrs": {"attr1": 'green', "attr2": 'hight'}}
}
# Subclass string, so we can add attributes to the instance.
class Item(str):
def __new__(cls, d):
s = super().__new__(cls, d["ref"])
s.attrs = d["attrs"]
return s
# Just a class that holds the dict keys as attributes
# and Item objects as their values.
class Items:
def __init__(self, d):
for it in d:
setattr(self, it, Item(d[it]))
i = Items(items)
print(i.i1)
print(i.i1.attrs)
output:
i1_ref
{'attr1': 'red', 'attr2': 'low'}
Different solution with SimpleNamespace
:
from types import SimpleNamespace
items = {
"i1": {"ref": "i1_ref", "attrs": {"attr1": 'red', "attr2": 'low'}},
"i2": {"ref": "i2_def", "attrs": {"attr1": 'green', "attr2": 'hight'}}
}
class Item(SimpleNamespace):
def __str__(self):
return self.ref
i = SimpleNamespace(**{k:Item(**v) for k,v in items.items()})
print(i.i1)
print(i.i1.attrs)
Although the printed output is exactly the same, the behavior is a bit different:
While i.i1
from the first solution really is a string (with attached attrs
), i.i1
from the second solution is a SimpleNamespace
object whose string representation is the ref
.
This means i.i1 == "i1_ref"
is True
for the first solution, but for the second solution you need to write str(i.i1) == "i1_ref"
or i.i1.ref == "i1_ref"
.
Upvotes: 1