优雅的方法来检查字典中是否存在嵌套键?

发布于 2021-01-29 15:06:11

是否有更可读的方法来检查是否存在嵌入字典的键而无需独立检查每个级别?

可以说我需要在埋藏的对象中获取此值(示例取自Wikidata):

x = s['mainsnak']['datavalue']['value']['numeric-id']

为了确保不会以运行时错误结束,有必要检查每个级别,如下所示:

if 'mainsnak' in s and 'datavalue' in s['mainsnak'] and 'value' in s['mainsnak']['datavalue'] and 'nurmeric-id' in s['mainsnak']['datavalue']['value']:
    x = s['mainsnak']['datavalue']['value']['numeric-id']

我可以想到的另一种解决方法是将其包装到一个try catch结构中,对于这样一个简单的任务,我也觉得很尴尬。

我正在寻找类似的东西:

x = exists(s['mainsnak']['datavalue']['value']['numeric-id'])

True如果所有级别都存在,则返回。

关注者
0
被浏览
54
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    简而言之,使用Python,您必须相信请求宽恕比允许许可容易

    try:
        x = s['mainsnak']['datavalue']['value']['numeric-id']
    except KeyError:
        pass
    

    答案

    这是我处理嵌套dict键的方法:

    def keys_exists(element, *keys):
        '''
        Check if *keys (nested) exists in `element` (dict).
        '''
        if not isinstance(element, dict):
            raise AttributeError('keys_exists() expects dict as first argument.')
        if len(keys) == 0:
            raise AttributeError('keys_exists() expects at least two arguments, one given.')
    
        _element = element
        for key in keys:
            try:
                _element = _element[key]
            except KeyError:
                return False
        return True
    

    例:

    data = {
        "spam": {
            "egg": {
                "bacon": "Well..",
                "sausages": "Spam egg sausages and spam",
                "spam": "does not have much spam in it"
            }
        }
    }
    
    print 'spam (exists): {}'.format(keys_exists(data, "spam"))
    print 'spam > bacon (do not exists): {}'.format(keys_exists(data, "spam", "bacon"))
    print 'spam > egg (exists): {}'.format(keys_exists(data, "spam", "egg"))
    print 'spam > egg > bacon (exists): {}'.format(keys_exists(data, "spam", "egg", "bacon"))
    

    输出:

    spam (exists): True
    spam > bacon (do not exists): False
    spam > egg (exists): True
    spam > egg > bacon (exists): True
    

    它以给element定的顺序循环测试给定的每个键。

    variable.get('key', {})我发现的所有方法相比,我都更喜欢此方法,因为它遵循EAFP

    功能除外,例如:keys_exists(dict_element_to_test, 'key_level_0', 'key_level_1', 'key_level_n', ..)。至少需要两个参数,元素和一个键,但是您可以添加所需的键数。

    如果您需要使用某种地图,则可以执行以下操作:

    expected_keys = ['spam', 'egg', 'bacon']
    keys_exists(data, *expected_keys)
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看