我有一本嵌套的字典。是否只有一种方法可以安全地传递价值观?

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

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


当前回答

我使用的一个解决方案类似于double get,但具有使用if else逻辑避免TypeError的额外能力:

    value = example_dict['key1']['key2'] if example_dict.get('key1') and example_dict['key1'].get('key2') else default_value

然而,字典嵌套越多,这就变得越麻烦。

其他回答

我的实现下降到子字典,忽略None值,但失败与TypeError如果发现任何其他

def deep_get(d: dict, *keys, default=None):
    """ Safely get a nested value from a dict

    Example:
        config = {'device': None}
        deep_get(config, 'device', 'settings', 'light')
        # -> None
        
    Example:
        config = {'device': True}
        deep_get(config, 'device', 'settings', 'light')
        # -> TypeError

    Example:
        config = {'device': {'settings': {'light': 'bright'}}}
        deep_get(config, 'device', 'settings', 'light')
        # -> 'light'

    Note that it returns `default` is a key is missing or when it's None.
    It will raise a TypeError if a value is anything else but a dict or None.
    
    Args:
        d: The dict to descend into
        keys: A sequence of keys to follow
        default: Custom default value
    """
    # Descend while we can
    try:
        for k in keys:
            d = d[k]
    # If at any step a key is missing, return default
    except KeyError:
        return default
    # If at any step the value is not a dict...
    except TypeError:
        # ... if it's a None, return default. Assume it would be a dict.
        if d is None:
            return default
        # ... if it's something else, raise
        else:
            raise
    # If the value was found, return it
    else:
        return d

对于二级键检索,你可以这样做:

key2_value = (example_dict.get('key1') or {}).get('key2')

对于嵌套的字典/JSON查找,可以使用dictor

PIP安装指示器

dict对象

{
    "characters": {
        "Lonestar": {
            "id": 55923,
            "role": "renegade",
            "items": [
                "space winnebago",
                "leather jacket"
            ]
        },
        "Barfolomew": {
            "id": 55924,
            "role": "mawg",
            "items": [
                "peanut butter jar",
                "waggy tail"
            ]
        },
        "Dark Helmet": {
            "id": 99999,
            "role": "Good is dumb",
            "items": [
                "Shwartz",
                "helmet"
            ]
        },
        "Skroob": {
            "id": 12345,
            "role": "Spaceballs CEO",
            "items": [
                "luggage"
            ]
        }
    }
}

要获得龙星的物品,只需提供一个点分隔的路径,即

import json
from dictor import dictor

with open('test.json') as data: 
    data = json.load(data)

print dictor(data, 'characters.Lonestar.items')

>> [u'space winnebago', u'leather jacket']

如果键不在路径中,您可以提供回退值

你还有很多选择,比如忽略字母大小写,使用'以外的其他字符。作为路径分隔符,

https://github.com/perfecto25/dictor

你也可以使用python reduce:

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

我建议你试试蟒蛇本尼迪克特。

它是一个dict子类,提供小键盘支持等功能。

安装:pip install python-benedict

from benedict import benedict

example_dict = benedict(example_dict, keypath_separator='.')

现在你可以使用keypath访问嵌套值:

val = example_dict['key1.key2']

# using 'get' method to avoid a possible KeyError:
val = example_dict.get('key1.key2')

或者使用键列表访问嵌套值:

val = example_dict['key1', 'key2']

# using get to avoid a possible KeyError:
val = example_dict.get(['key1', 'key2'])

它在GitHub上经过了很好的测试和开源:

https://github.com/fabiocaccamo/python-benedict

注:我是这个项目的作者