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


问题内容

我有一本嵌套的字典。是否只有一种安全地获取价值的方法?

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

也许python有像get()嵌套字典这样的方法?


问题答案:

您可以使用get两次:

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

None如果存在key1key2不存在,它将返回。

请注意,这仍然可以引发AttributeErrorifexample_dict['key1']存在但不是dict(或带有get方法的类似dict的对象)。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是的子类,所以dict您可以像使用一样使用Hasher
dict。可以使用所有相同的方法和语法,而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')