【发布时间】:2020-07-21 22:14:15
【问题描述】:
我想实现一个类似dict的数据结构,它具有以下属性:
from collections import UserDict
class TestDict(UserDict):
pass
test_dict = TestDict()
# Create empty dictionaries at 'level_1' and 'level_2' and insert 'Hello' at the 'level_3' key.
test_dict['level_1']['level_2']['level_3'] = 'Hello'
>>> test_dict
{
'level_1': {
'level_2': {
'level_3': 'Hello'
}
}
}
# However, this should not return an empty dictionary but raise a KeyError.
>>> test_dict['unknown_key']
KeyError: 'unknown_key'
据我所知,问题是python不知道__getitem__是在设置项目的上下文中被调用的,即第一个例子,还是在获取和项目的上下文中,第二个例子。
我已经看过Python `defaultdict`: Use default when setting, but not when getting,但我不认为这个问题是重复的,或者它回答了我的问题。
如果您有任何想法,请告诉我。
提前致谢。
编辑:
使用以下方法可以实现类似的效果:
def set_nested_item(dict_in: Union[dict, TestDict], value, keys):
for i, key in enumerate(keys):
is_last = i == (len(keys) - 1)
if is_last:
dict_in[key] = value
else:
if key not in dict_in:
dict_in[key] = {}
else:
if not isinstance(dict_in[key], (dict, TestDict)):
dict_in[key] = {}
dict_in[key] = set_nested_item(dict_in[key], value, keys[(i + 1):])
return dict_in
class TestDict(UserDict):
def __init__(self):
super().__init__()
def __setitem__(self, key, value):
if isinstance(key, list):
self.update(set_nested_item(self, value, key))
else:
super().__setitem__(key, value)
test_dict[['level_1', 'level_2', 'level_3']] = 'Hello'
>>> test_dict
{
'level_1': {
'level_2': {
'level_3': 'Hello'
}
}
}
【问题讨论】:
-
当前想法:覆盖
__setitem__以接受列表作为键。列表不能是字典键,因此当您发出test_dict[['level_1', 'level_2', 'level_3']] = 'Hello'时,该方法应该下降到内部字典或根据需要创建它们。这不是你要求的,但这是我能得到的最接近的。 -
@timgeb 谢谢,必须这样做。添加了一个编辑。
标签: python dictionary defaultdict