我如何使Python字典成员访问通过点“。”?
例如,我想写mydict.val而不是mydict['val']。
我还想以这种方式访问嵌套字典。例如
mydict.mydict2.val
会提到
mydict = { 'mydict2': { 'val': ... } }
我如何使Python字典成员访问通过点“。”?
例如,我想写mydict.val而不是mydict['val']。
我还想以这种方式访问嵌套字典。例如
mydict.mydict2.val
会提到
mydict = { 'mydict2': { 'val': ... } }
当前回答
派生自dict和并实现__getattr__和__setattr__。
或者你也可以用Bunch,非常相似。
我不认为这是可能的monkeypatch内置字典类。
其他回答
不喜欢。在Python中,属性访问和索引是分开的事情,您不应该希望它们执行相同的操作。创建一个类(可能是由namedtuple创建的),如果你有一些应该具有可访问属性的东西,并使用[]符号从字典中获取一个项。
这也适用于嵌套字典,并确保后面追加的字典行为相同:
class DotDict(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Recursively turn nested dicts into DotDicts
for key, value in self.items():
if type(value) is dict:
self[key] = DotDict(value)
def __setitem__(self, key, item):
if type(item) is dict:
item = DotDict(item)
super().__setitem__(key, item)
__setattr__ = __setitem__
__getattr__ = dict.__getitem__
我喜欢Munch,它提供了很多方便的选项在点访问。
进口蒙克 Temp_1 = {'person': {' fname': 'senthil', 'lname': 'ramalingam'}} Dict_munch = munch.munchify(temp_1) dict_munch.person.fname
这是我从很久以前的一个项目里挖出来的。它可能还可以再优化一点,但就是这样了。
class DotNotation(dict):
__setattr__= dict.__setitem__
__delattr__= dict.__delitem__
def __init__(self, data):
if isinstance(data, str):
data = json.loads(data)
for name, value in data.items():
setattr(self, name, self._wrap(value))
def __getattr__(self, attr):
def _traverse(obj, attr):
if self._is_indexable(obj):
try:
return obj[int(attr)]
except:
return None
elif isinstance(obj, dict):
return obj.get(attr, None)
else:
return attr
if '.' in attr:
return reduce(_traverse, attr.split('.'), self)
return self.get(attr, None)
def _wrap(self, value):
if self._is_indexable(value):
# (!) recursive (!)
return type(value)([self._wrap(v) for v in value])
elif isinstance(value, dict):
return DotNotation(value)
else:
return value
@staticmethod
def _is_indexable(obj):
return isinstance(obj, (tuple, list, set, frozenset))
if __name__ == "__main__":
test_dict = {
"dimensions": {
"length": "112",
"width": "103",
"height": "42"
},
"meta_data": [
{
"id": 11089769,
"key": "imported_gallery_files",
"value": [
"https://example.com/wp-content/uploads/2019/09/unnamed-3.jpg",
"https://example.com/wp-content/uploads/2019/09/unnamed-2.jpg",
"https://example.com/wp-content/uploads/2019/09/unnamed-4.jpg"
]
}
]
}
dotted_dict = DotNotation(test_dict)
print(dotted_dict.dimensions.length) # => '112'
print(getattr(dotted_dict, 'dimensions.length')) # => '112'
print(dotted_dict.meta_data[0].key) # => 'imported_gallery_files'
print(getattr(dotted_dict, 'meta_data.0.key')) # => 'imported_gallery_files'
print(dotted_dict.meta_data[0].value) # => ['link1','link2','link2']
print(getattr(dotted_dict, 'meta_data.0.value')) # => ['link1','link2','link3']
print(dotted_dict.meta_data[0].value[2]) # => 'link3'
print(getattr(dotted_dict, 'meta_data.0.value.2')) # => 'link3'
可以使用dotsi来支持完整列表、dict和递归,并使用一些扩展方法
pip install dotsi
and
>>> import dotsi
>>>
>>> d = dotsi.Dict({"foo": {"bar": "baz"}}) # Basic
>>> d.foo.bar
'baz'
>>> d.users = [{"id": 0, "name": "Alice"}] # List
>>> d.users[0].name
'Alice'
>>> d.users.append({"id": 1, "name": "Becca"}); # Append
>>> d.users[1].name
'Becca'
>>> d.users += [{"id": 2, "name": "Cathy"}]; # `+=`
>>> d.users[2].name
'Cathy'
>>> d.update({"tasks": [{"id": "a", "text": "Task A"}]});
>>> d.tasks[0].text
'Task A'
>>> d.tasks[0].tags = ["red", "white", "blue"];
>>> d.tasks[0].tags[2];
'blue'
>>> d.tasks[0].pop("tags") # `.pop()`
['red', 'white', 'blue']
>>>
>>> import pprint
>>> pprint.pprint(d)
{'foo': {'bar': 'baz'},
'tasks': [{'id': 'a', 'text': 'Task A'}],
'users': [{'id': 0, 'name': 'Alice'},
{'id': 1, 'name': 'Becca'},
{'id': 2, 'name': 'Cathy'}]}
>>>
>>> type(d.users) # dotsi.Dict (AKA dotsi.DotsiDict)
<class 'dotsi.DotsiList'>
>>> type(d.users[0]) # dotsi.List (AKA dotsi.DotsiList)
<class 'dotsi.DotsiDict'>
>>>