链接,嵌套的字典()获得蟒蛇电话(Chained, nested dict() get calls

2019-07-18 14:38发布

我询问使用dict.get(“关键字”)方法的嵌套字典。 目前,我的语法是...

M = cursor_object_results_of_db_query

for m in M:
    X = m.get("gparents").get("parent").get("child")
    for x in X:
        y = x.get("key")

但是,有时“父母”和“孩子”标签中的一个不存在的,而我的脚本失败。 我知道使用get() ,我可以包括的情况下默认的键不存在形式的...

get("parent", '') or
get("parent", 'orphan') 

但是,如果我有任何Null'' ,或者空我能想到的,链式.get("child")的调用时失败''.get("child")因为""有没有一种方法.get()

现在我解决这个的方法是使用一串连续的try-except各地各.get("")调用,但似乎愚蠢和unpython ---是有办法的默认返回"skip""pass"什么,将仍然支持链接和失败智能,而不是深入了解不存在的钥匙?

理想情况下,我想这是形式的列表理解:

[m.get("gparents").get("parent").get("child") for m in M]

但当父母缺席的原因,这是目前不可能.get("child")呼吁终止我的程序。

Answer 1:

由于这些是所有的Python dict S和您呼叫的dict.get()对他们的方法,你可以使用一个空的dict ,以链:

[m.get("gparents", {}).get("parent", {}).get("child") for m in M]

通过不使用最后的默认.get()你退回到None 。 现在,如果任何中介钥匙没找到,该链的其余部分将使用空字典看东西,在终端.get('child')返回None



Answer 2:

另一种方法是要认识到,如果关键是没有找到, dict.get返回None 。 但是, None不具备的属性.get ,所以它会抛出一个AttributeError

for m in M:
    try:
       X = m.get("gparents").get("parent").get("child")
    except AttributeError:
       continue

    for x in X:
        y = x.get("key")
        #do something with `y` probably???

就像马亭的答案,这并不能保证X是迭代(非None )。 虽然,你可以修复,通过使最后的get链中的默认返回一个空列表:

 try:
    X = m.get("gparents").get("parent").get("child",[])
 except AttributeError:
    continue

最后,我想可能是这个问题的最好解决方案是使用reduce

try:
    X = reduce(dict.__getitem__,["gparents","parent","child"],m)
except (KeyError,TypeError):
    pass
else:
    for x in X:
       #do something with x

这里的好处是,你知道,如果任何的get S的基于时引发异常的类型失败。 这有可能是一个get返回错误的类型,那么你得到一个TypeError 。 如果字典里没有钥匙但是,它提出了一个KeyError 。 您可以单独或一起处理这些。 无论最适合您的使用情况。



Answer 3:

如何使用小助手功能?

def getn(d, path):
    for p in path:
        if p not in d:
            return None
        d = d[p]
    return d

然后

[getn(m, ["gparents", "parent", "child"]) for m in M]


Answer 4:

我意识到我的部分有点晚了,但这里是我想出了在面对类似的问题与解决方案:

def get_nested(dict_, *keys, default=None):
    if not isinstance(dict_, dict):
        return default
    elem = dict_.get(keys[0], default)
    if len(keys) == 1:
        return elem
    return get_nested(elem, *keys[1:], default=default)

例如:

In [29]: a = {'b': {'c': 1}}
In [30]: get_nested(a, 'b', 'c')
Out[30]: 1
In [31]: get_nested(a, 'b', 'd') is None
Out[31]: True


文章来源: Chained, nested dict() get calls in python