Python:轻松访问深度嵌套的字典(获取和设置)

Python:轻松访问深度嵌套的字典(获取和设置),第1张

Python:轻松访问深度嵌套的字典(获取和设置) 属性树

第一个规范的问题在于,Python无法告诉您

__getitem__
,在处
my_obj.a.b.c.d
,您是否下一步将继续沿着不存在的树进行 *** 作,在这种情况下,它需要使用一种
__getitem__
方法返回一个对象,因此您不会被
AttributeError
抛出,或者如果您想要一个值,则需要返回
None

我认为,在每种情况下,您都应该期望它抛出

KeyError
而不是返回
None
。原因是您无法分辨是否
None
表示“无钥匙”或“实际存储
None
在该位置的人”。对于此行为,您所需要做的就是take
dotdictify
,remove
marker
和替换
__getitem__
为:

def __getitem__(self, key):    return self[key]

因为您真正想要的是

dict
with
__getattr__
__setattr__

可能有一种方法可以

__getitem__
完全删除并说一些类似的内容
__getattr__ =dict.__getitem__
,但是我认为这可能是过度优化的问题,如果您以后决定要
__getitem__
dotdictify
最初那样创建树,那么这将是一个问题,在这种情况下,您会更改为:

def __getitem__(self, key):    if key not in self:        dict.__setitem__(self, key, dotdictify())    return dict.__getitem__(self, key)

我不喜欢

marker
原来的生意
dotdictify

路径支持

第二个规范(override

get()
set()
)是,法线
dict
get()
*** 作与您描述的不同,甚至不包含
set
(尽管其
setdefault()
*** 作与 *** 作相反
get()
)。人们期望
get
采用两个参数,如果找不到密钥,则第二个参数为默认值。

如果要扩展

__getitem__
__setitem__
处理点键符号,则需要修改
doctictify
为:

class dotdictify(dict):    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 '.' in key: myKey, restOfKey = key.split('.', 1) target = self.setdefault(myKey, dotdictify()) if not isinstance(target, dotdictify):     raise KeyError, 'cannot set "%s" in "%s" (%s)' % (restOfKey, myKey, repr(target)) target[restOfKey] = value        else: if isinstance(value, dict) and not isinstance(value, dotdictify):     value = dotdictify(value) dict.__setitem__(self, key, value)    def __getitem__(self, key):        if '.' not in key: return dict.__getitem__(self, key)        myKey, restOfKey = key.split('.', 1)        target = dict.__getitem__(self, myKey)        if not isinstance(target, dotdictify): raise KeyError, 'cannot get "%s" in "%s" (%s)' % (restOfKey, myKey, repr(target))        return target[restOfKey]    def __contains__(self, key):        if '.' not in key: return dict.__contains__(self, key)        myKey, restOfKey = key.split('.', 1)        target = dict.__getitem__(self, myKey)        if not isinstance(target, dotdictify): return False        return restOfKey in target    def setdefault(self, key, default):        if key not in self: self[key] = default        return self[key]    __setattr__ = __setitem__    __getattr__ = __getitem__

测试代码:

>>> life = dotdictify({'bigBang': {'stars': {'planets': {}}}})>>> life.bigBang.stars.planets{}>>> life.bigBang.stars.planets.earth = { 'singleCellLife' : {} }>>> life.bigBang.stars.planets{'earth': {'singleCellLife': {}}}>>> life['bigBang.stars.planets.mars.landers.vikings'] = 2>>> life.bigBang.stars.planets.mars.landers.vikings2>>> 'landers.vikings' in life.bigBang.stars.planets.marsTrue>>> life.get('bigBang.stars.planets.mars.landers.spirit', True)True>>> life.setdefault('bigBang.stars.planets.mars.landers.opportunity', True)True>>> 'landers.opportunity' in life.bigBang.stars.planets.marsTrue>>> life.bigBang.stars.planets.mars{'landers': {'opportunity': True, 'vikings': 2}}


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5666728.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-16
下一篇2022-12-16

发表评论

登录后才能评论

评论列表(0条)

    保存