Python 安全字典导航,正确的方法

问题描述 投票:0回答:4

TLDR 总结

我编写了一个函数

navigateDict
,它可以在
dict
上进行安全导航,类似于
dict.get()
但嵌套。它取代了类似的代码

if 1 in data and 'i' in data[1] and 'a' in data[1]['i']:
    print data[1]['i']['a']
else:
    print "Not found"

大致相当

found = navigateDict(data, 1, 'i', 'a')
if found is not None:
    print found
else:
    print "Not found"
  • 标准库中已经有类似的东西了吗?
  • 有没有更惯用的方法来做同样的事情?
    • 任何需要多次输入任何路径组件键的响应都可能不是答案。

其他详细信息

实现如下:

# Allow fallback value other than None
def navigateDictEx(d, keys, fallback=None):
    for key in keys:
        if key in d:
            d = d[key]
        else:
            return fallback
    return d

def navigateDict(d, *keys):
    return navigateDictEx(d, keys)

请参阅摘要以了解示例用法。

无论是否Pythonic,这个函数都会减少冗余不是一个好主意的地方的重复。例如,更改示例中的一个路径组件需要将最多三个不同的值修改为原始示例中的一个,但在修改后的示例中只需要修改一个。鉴于我经常犯错,这是一个巨大的胜利。

最终我要问:标准库中是否有东西可以做到这一点,或者我是否需要在我的项目库中找到它的位置?

如果预计命中率将超过未命中率

brionius 正确地指出,抓住

KeyError
会起作用:

try:
    print data[1]['i']['a']
except KeyError:
    print "Not found"

这可能就是我要走的路;它非常简洁并且减少了重复。然而,它确实反映了一个假设,即命中率将多于未命中率。如果有更好的方法来假设相反的情况,我也想知道。

python dictionary idioms
4个回答
11
投票

执行此操作的一种方法如下:

try:
    print data[1]['i']['a']
except KeyError:
    print "Not found!"

符合鸭子打字的精神。它可能会或可能不会那么快,因为我相信处理异常会带来一定的开销,但它肯定是“安全的”。


5
投票

这样的解决方案很酷

https://twitter.com/raymondh/status/343823801278140417

>>> from collections import defaultdict
>>> infinite_defaultdict = lambda: defaultdict(infinite_defaultdict)
>>> d = infinite_defaultdict() 
>>> d['x']['y']['z'] = 10
>>> if d['x']['y']['z']: print d['x']['y']['z'] #better reflects that misses are common

0
投票

我知道的最简单的解决方案是链接

.get(_, {})
调用。

my_dict.get(1, {}).get(2, {})

-2
投票

这个游戏迟到了好几年,但对于任何偶然发现这一点的人来说,似乎仍然没有一种原生、流畅的方法来安全地导航 Python 字典。

输入休息响应

“RestResponse 旨在成为一个流畅的 Python 对象,用于与 RESTful JSON API 交互”

该库包含一个 NoneProp 对象,允许安全地导航(和构建)JSON 数据结构。

>>> import RestResponse
>>> data = RestResponse.parse({})
>>> data.property.is_none
None
>>> bool(data.property.is_none)
False
>>> isinstance(data.property.is_none, RestResponse.NoneProp)
True
>>> data.property.is_none = None
>>> isinstance(data.property.is_none, RestResponse.NoneProp)
False
>>> print data.pretty_print()
{
    "property": {
        "is_none": null
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.