Art*_*rti 111 python methods dictionary except
我有一个嵌套字典.是否只有一种方法可以安全地获得价值?
try:
example_dict['key1']['key2']
except KeyError:
pass
Run Code Online (Sandbox Code Playgroud)
或者python有一个像get()
嵌套字典的方法?
unu*_*tbu 215
你可以使用get
两次:
example_dict.get('key1', {}).get('key2')
Run Code Online (Sandbox Code Playgroud)
None
如果存在key1
或key2
不存在,则返回.
请注意,这仍然可以引发AttributeError
if example_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'>
Run Code Online (Sandbox Code Playgroud)
请注意,当缺少键时,这将返回空Hasher.
既然Hasher
是dict
你的子类,你可以使用Hasher,就像使用a一样dict
.所有相同的方法和语法都可用,Hashers只是以不同的方式处理丢失的密钥.
您可以将常规dict
转换为Hasher
如下所示:
hasher = Hasher(example_dict)
Run Code Online (Sandbox Code Playgroud)
并轻松地将a转换Hasher
为常规dict
:
regular_dict = dict(hasher)
Run Code Online (Sandbox Code Playgroud)
另一个选择是隐藏辅助函数中的丑陋:
def safeget(dct, *keys):
for key in keys:
try:
dct = dct[key]
except KeyError:
return None
return dct
Run Code Online (Sandbox Code Playgroud)
因此,其余代码可以保持相对可读性:
safeget(example_dict, 'key1', 'key2')
Run Code Online (Sandbox Code Playgroud)
小智 50
你也可以使用python reduce:
def deep_get(dictionary, *keys):
return reduce(lambda d, key: d.get(key) if d else None, keys, dictionary)
Run Code Online (Sandbox Code Playgroud)
oli*_*679 30
在第一阶段,您可以获取一个空字典。
example_dict.get('key1',{}).get('key2')
Run Code Online (Sandbox Code Playgroud)
Yud*_*ira 24
通过在这里结合所有这些答案和我所做的小改动,我认为这个功能将是有用的.它安全,快速,易于维护.
def deep_get(dictionary, keys, default=None):
return reduce(lambda d, key: d.get(key, default) if isinstance(d, dict) else default, keys.split("."), dictionary)
Run Code Online (Sandbox Code Playgroud)
示例:
>>> from functools import reduce
>>> def deep_get(dictionary, keys, default=None):
... return reduce(lambda d, key: d.get(key, default) if isinstance(d, dict) else default, keys.split("."), dictionary)
...
>>> person = {'person':{'name':{'first':'John'}}}
>>> print (deep_get(person, "person.name.first"))
John
>>> print (deep_get(person, "person.name.lastname"))
None
>>> print (deep_get(person, "person.name.lastname", default="No lastname"))
No lastname
>>>
Run Code Online (Sandbox Code Playgroud)
Jos*_*ban 14
建立Yoav的答案,更安全的方法:
def deep_get(dictionary, *keys):
return reduce(lambda d, key: d.get(key, None) if isinstance(d, dict) else None, keys, dictionary)
Run Code Online (Sandbox Code Playgroud)
hoe*_*ing 10
glom
是一个不错的库,也可以进行点查询:
In [1]: from glom import glom
In [2]: data = {'a': {'b': {'c': 'd'}}}
In [3]: glom(data, "a.b.c")
Out[3]: 'd'
Run Code Online (Sandbox Code Playgroud)
查询失败有一个很好的堆栈跟踪,指示确切的失败点:
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')
Run Code Online (Sandbox Code Playgroud)
保障措施default
:
In [5]: glom(data, "a.b.foo", default="spam")
Out[5]: 'spam'
Run Code Online (Sandbox Code Playgroud)
其优点glom
在于多功能的规格参数。例如,可以轻松地从以下内容中提取所有名字data
:
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']
Run Code Online (Sandbox Code Playgroud)
阅读glom
文档以获取更多示例。
您可以使用 pydash:
import pydash as _ #NOTE require `pip install pydash`
_.get(example_dict, 'key1.key2', default='Default')
Run Code Online (Sandbox Code Playgroud)
https://pydash.readthedocs.io/en/latest/api.html
我建议你试试python-benedict
。
它是一个dict
提供 keypath 支持等的子类。
安装: pip install python-benedict
from benedict import benedict
example_dict = benedict(example_dict, keypath_separator='.')
Run Code Online (Sandbox Code Playgroud)
现在您可以使用keypath访问嵌套值:
from benedict import benedict
example_dict = benedict(example_dict, keypath_separator='.')
Run Code Online (Sandbox Code Playgroud)
或使用键列表访问嵌套值:
val = example_dict['key1.key2']
# using 'get' method to avoid a possible KeyError:
val = example_dict.get('key1.key2')
Run Code Online (Sandbox Code Playgroud)
它在 GitHub 上经过良好测试和开源:
https://github.com/fabiocaccamo/python-benedict
注意:我是这个项目的作者
递归解决方案.它不是最有效的,但我发现它比其他示例更具可读性,并且它不依赖于functools.
def deep_get(d, keys):
if not keys or d is None:
return d
return deep_get(d.get(keys[0]), keys[1:])
Run Code Online (Sandbox Code Playgroud)
例
d = {'meta': {'status': 'OK', 'status_code': 200}}
deep_get(d, ['meta', 'status_code']) # => 200
deep_get(d, ['garbage', 'status_code']) # => None
Run Code Online (Sandbox Code Playgroud)
更精致的版本
def deep_get(d, keys, default=None):
"""
Example:
d = {'meta': {'status': 'OK', 'status_code': 200}}
deep_get(d, ['meta', 'status_code']) # => 200
deep_get(d, ['garbage', 'status_code']) # => None
deep_get(d, ['meta', 'garbage'], default='-') # => '-'
"""
assert type(keys) is list
if d is None:
return default
if not keys:
return d
return deep_get(d.get(keys[0]), keys[1:], default)
Run Code Online (Sandbox Code Playgroud)
虽然简化方法很简洁,但我认为简单的循环更容易理解.我还包括一个默认参数.
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
Run Code Online (Sandbox Code Playgroud)
作为了解减少单线程如何工作的练习,我做了以下工作.但最终循环方法对我来说似乎更直观.
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)
Run Code Online (Sandbox Code Playgroud)
用法
nested = {'a': {'b': {'c': 42}}}
print deep_get(nested, ['a', 'b'])
print deep_get(nested, ['a', 'b', 'z', 'z'], default='missing')
Run Code Online (Sandbox Code Playgroud)
从 Python 3.4 开始,您可以使用它with suppress (KeyError)
来访问嵌套的 json 对象,而不必担心 Keyerror
from contextlib import suppress
with suppress(KeyError):
a1 = json_obj['key1']['key2']['key3']
a2 = json_obj['key4']['key5']['key6']
a3 = json_obj['key7']['key8']['key9']
Run Code Online (Sandbox Code Playgroud)
由泰龙提供。看看他的答案以获取更多详细信息:/sf/answers/3211197601/
归档时间: |
|
查看次数: |
85833 次 |
最近记录: |