获取嵌套字典值的安全方法

新手上路,请多包涵

我有一个嵌套字典。是否只有一种方法可以安全地取出值?

 try:
    example_dict['key1']['key2']
except KeyError:
    pass

或者也许 python 有一个类似 get() 的方法用于嵌套字典?

原文由 Arti 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 429
2 个回答

您可以使用 get 两次:

 example_dict.get('key1', {}).get('key2')

这将返回 None 如果 key1key2 不存在。

请注意,如果 example_dict['key1'] 存在但不是字典(或具有 get 方法的类似字典的对象),这仍然可能引发 AttributeError 。您发布的 try..except 代码将引发 TypeError 而不是 example_dict['key1'] 是不可订阅的。

另一个区别是 try...except 在第一个丢失的键之后立即短路。 get 调用链没有。


如果您希望保留语法 example_dict['key1']['key2'] 但不希望它引发 KeyErrors,那么您可以使用 Hasher 配方

 class Hasher(dict):
    # https://stackoverflow.com/a/3405143/190597
    def __missing__(self, key):
        value = self[key] = type(self)()
        return value

example_dict = Hasher()
print(example_dict['key1'])
# {}
print(example_dict['key1']['key2'])
# {}
print(type(example_dict['key1']['key2']))
# <class '__main__.Hasher'>

请注意,当缺少密钥时,这会返回一个空的 Hasher。

因为 Hasher 是 --- 的子类, dict 你可以像使用 dict 一样使用 Hasher。所有相同的方法和语法都可用,Hashers 只是以不同的方式处理缺失的键。

您可以将常规 dict 转换为 Hasher 如下所示:

 hasher = Hasher(example_dict)

并将 Hasher 转换为常规 dict 同样容易:

 regular_dict = dict(hasher)


另一种选择是在辅助函数中隐藏丑陋之处:

 def safeget(dct, *keys):
    for key in keys:
        try:
            dct = dct[key]
        except KeyError:
            return None
    return dct

所以你的代码的其余部分可以保持相对可读性:

 safeget(example_dict, 'key1', 'key2')

原文由 unutbu 发布,翻译遵循 CC BY-SA 3.0 许可协议

你也可以使用 python reduce

 def deep_get(dictionary, *keys):
    return reduce(lambda d, key: d.get(key) if d else None, keys, dictionary)

原文由 Yoav T 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题