栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

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

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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}}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/660612.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号