我有一本嵌套的字典。是否只有一种方法可以安全地传递价值观?
try:
example_dict['key1']['key2']
except KeyError:
pass
或者python有一个类似get()的方法用于嵌套字典?
我有一本嵌套的字典。是否只有一种方法可以安全地传递价值观?
try:
example_dict['key1']['key2']
except KeyError:
pass
或者python有一个类似get()的方法用于嵌套字典?
当前回答
我改编了GenesRus和unutbu的答案,非常简单:
class new_dict(dict):
def deep_get(self, *args, default=None):
_empty_dict = {}
out = self
for key in args:
out = out.get(key, _empty_dict)
return out if out else default
它适用于:
d = new_dict(some_data)
d.deep_get("key1", "key2", "key3", ..., default=some_value)
其他回答
你可以使用开源ndicts包中的NestedDict(我是作者),它有一个完全像字典一样的安全get方法。
>>> from ndicts import NestedDict
>>> nd = NestedDict({"key1": {"key2": 0}}
>>> nd.get(("key1", "key2))
0
>>> nd.get("asd")
虽然reduce方法简洁而简短,但我认为简单的循环更容易理解。我还包含了一个默认参数。
def deep_get(_dict, keys, default=None):
for key in keys:
if isinstance(_dict, dict):
_dict = _dict.get(key, default)
else:
return default
return _dict
作为理解reduce一行程序如何工作的练习,我执行了以下操作。但最终循环方法对我来说似乎更直观。
def deep_get(_dict, keys, default=None):
def _reducer(d, key):
if isinstance(d, dict):
return d.get(key, default)
return default
return reduce(_reducer, keys, _dict)
使用
nested = {'a': {'b': {'c': 42}}}
print deep_get(nested, ['a', 'b'])
print deep_get(nested, ['a', 'b', 'z', 'z'], default='missing')
减少方法的改进很少,使其与列表一起工作。也使用数据路径作为字符串除以点,而不是数组。
def deep_get(dictionary, path):
keys = path.split('.')
return reduce(lambda d, key: d[int(key)] if isinstance(d, list) else d.get(key) if d else None, keys, dictionary)
def safeget(_dct, *_keys):
if not isinstance(_dct, dict): raise TypeError("Is not instance of dict")
def foo(dct, *keys):
if len(keys) == 0: return dct
elif not isinstance(_dct, dict): return None
else: return foo(dct.get(keys[0], None), *keys[1:])
return foo(_dct, *_keys)
assert safeget(dict()) == dict()
assert safeget(dict(), "test") == None
assert safeget(dict([["a", 1],["b", 2]]),"a", "d") == None
assert safeget(dict([["a", 1],["b", 2]]),"a") == 1
assert safeget({"a":{"b":{"c": 2}},"d":1}, "a", "b")["c"] == 2
Glom是一个很好的库,可以进入点查询:
In [1]: from glom import glom
In [2]: data = {'a': {'b': {'c': 'd'}}}
In [3]: glom(data, "a.b.c")
Out[3]: 'd'
查询失败有一个很好的堆栈跟踪,指出确切的故障点:
In [4]: glom(data, "a.b.foo")
---------------------------------------------------------------------------
PathAccessError Traceback (most recent call last)
<ipython-input-4-2a3467493ac4> in <module>
----> 1 glom(data, "a.b.foo")
~/.cache/pypoetry/virtualenvs/neural-knapsack-dE7ihQtM-py3.8/lib/python3.8/site-packages/glom/core.py in glom(target, spec, **kwargs)
2179
2180 if err:
-> 2181 raise err
2182 return ret
2183
PathAccessError: error raised while processing, details below.
Target-spec trace (most recent last):
- Target: {'a': {'b': {'c': 'd'}}}
- Spec: 'a.b.foo'
glom.core.PathAccessError: could not access 'foo', part 2 of Path('a', 'b', 'foo'), got error: KeyError('foo')
默认保护:
In [5]: glom(data, "a.b.foo", default="spam")
Out[5]: 'spam'
格洛姆的魅力在于多功能的规格参数。例如,可以很容易地从以下数据中提取所有的名字:
In [8]: data = {
...: "people": [
...: {"first_name": "Alice", "last_name": "Adams"},
...: {"first_name": "Bob", "last_name": "Barker"}
...: ]
...: }
In [9]: glom(data, ("people", ["first_name"]))
Out[9]: ['Alice', 'Bob']
更多的例子请阅读glom文档。