我正在使用dict.get('keyword')方法查询嵌套字典。目前我的语法是......
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 ---有没有办法默认返回{{ 1}}或"skip"
或者仍然支持链接并智能失败的东西,而不是深入研究不存在的密钥?
理想情况下,我希望这是对表单的列表理解:
"pass"
但是当缺席的父母导致[m.get("gparents").get("parent").get("child") for m in M]
来电终止我的程序时,这是不可能的。
答案 0 :(得分:63)
由于这些都是python dict
并且您在它们上调用dict.get()
方法,因此您可以使用空dict
来链接:
[m.get("gparents", {}).get("parent", {}).get("child") for m in M]
如果不使用上一个.get()
的默认设置,则会回退到None
。现在,如果找不到任何中间密钥,则链的其余部分将使用空字典查找内容,在.get('child')
返回None
后终止。
答案 1 :(得分:7)
另一种方法是识别如果找不到密钥,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???
就像Martijn的回答一样,这并不能保证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
是否失败。 get
可能会返回错误的类型,然后您会得到TypeError
。但是,如果字典没有密钥,则会引发KeyError
。您可以单独或一起处理这些。哪种最适合您的用例。
答案 2 :(得分:4)
如何使用小帮手功能?
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]
答案 3 :(得分:4)
我意识到我有点迟到了,但这是我遇到类似问题时提出的解决方案:
menuItem
例如:
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)