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

2025-02-10 08:57:00
admin
原创
56
摘要:问题描述:我有一个嵌套字典。是否只有一种方法可以安全地获取值?try: example_dict['key1']['key2'] except KeyError: pass 或者也许 python 有一个类似get()嵌套字典的方法?解决方案 1:您可以使用get两次:example_dict...

问题描述:

我有一个嵌套字典。是否只有一种方法可以安全地获取值?

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

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


解决方案 1:

您可以使用get两次:

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

None如果key1key2不存在则返回。

AttributeError请注意,如果example_dict['key1']存在但不是字典(或具有get方法的类似字典的对象),这仍会引发异常。如果不可下标,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。

由于Hasher是的子类,因此dict您可以像使用一样使用 Hasher dict。所有相同的方法和语法都可用,Hashers 只是以不同的方式处理缺失的键。

您可以将常规转换dictHasher如下形式:

hasher = Hasher(example_dict)

并同样轻松地将 a 转换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')

解决方案 2:

通过结合这里的所有这些答案和我所做的小改动,我认为这个功能会很有用。它安全、快速、易于维护。

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)

例子 :

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

解决方案 3:

您也可以使用 python reduce:

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

解决方案 4:

在第一阶段,您可以获得一本空的字典。

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

解决方案 5:

根据 Yoav 的回答,有一个更安全的方法:

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

解决方案 6:

递归解决方案。它不是最有效的,但我发现它比其他示例更具可读性,并且它不依赖于 functools。

def deep_get(d, keys):
    if not keys or d is None:
        return d
    return deep_get(d.get(keys[0]), keys[1:])

例子

d = {'meta': {'status': 'OK', 'status_code': 200}}
deep_get(d, ['meta', 'status_code'])     # => 200
deep_get(d, ['garbage', 'status_code'])  # => None

更精致的版本

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)

解决方案 7:

我建议你尝试一下python-benedict

它是一个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

注:我是这个项目的作者

解决方案 8:

虽然 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')

解决方案 9:

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')

保障方式default

In [5]: glom(data, "a.b.foo", default="spam")
Out[5]: 'spam'

的美妙之glom处在于其多功能的 spec 参数。例如,我们可以轻松地从以下内容中提取所有名字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']

阅读glom文档以获取更多示例。

解决方案 10:

单行解决方案

一种流行(但有潜在风险)的解决方案

接受的答案以及许多其他答案建议使用get()并将第二个参数设为空dict,如下所示:

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

example_dict在没有名为 的键的情况下,这种方法可以正常工作key1。但是,在这种情况下:

example_dict = {'key1': None}

我们会得到一个错误:

AttributeError: 'NoneType' object has no attribute 'get'

原因是表达式example_dict.get('key1', {})会返回None,因为key1 确实存在(因此该get()方法不会返回我们传递的默认值)。

另一种选择or(可能更安全)

为了解决上述问题,一个可能更安全的替代方法是这样做:

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

如果key1不存在,表达式的(example_dict.get('key1') or {})计算结果仍为空。但是当存在且为时,dict也会发生相同的情况。key1 None

这里我们利用了这样一个事实:在 Python 中,只要是值(就是其中之一),表达式a or b就会求值为。这意味着上述技巧不仅在时有效,而且在 等于、、、等时也有效。也许根本不会想到这些特殊情况,但在我的实践中,这更有可能是一个应该考虑的有效情况。b`aNonekey1NoneFalse[]0''None`

比较

以下是三个单行表达式的比较:

  1. example_dict['key1']['key2']

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

  3. (example_dict.get('key1') or {}).get('key2')

example_dict表达式 1表达式 2表达式 3
{}KeyError: 'key1'✔️ 确定 ( None)✔️ 确定 ( None)
{'key1': {}}KeyError: 'key2'✔️ 确定 ( None)✔️ 确定 ( None)
{'key1': {'key2': 123}}✔️ 确定 ( 123)✔️ 确定 ( 123)✔️ 确定 ( 123)
{'key1': None}TypeError1AttributeError2✔️ 确定 ( None)

1 TypeError: 'NoneType' object is not subscriptable

2 AttributeError: 'NoneType' object has no attribute 'get'

警告

所有这些单行解决方案对于偶尔使用来说都很方便。但如果发现经常需要这样的功能或需要更严格的验证,我建议使用特殊函数。

解决方案 11:

您可以使用 pydash:

import pydash as _  #NOTE require `pip install pydash`

_.get(example_dict, 'key1.key2', default='Default')

https://pydash.readthedocs.io/en/latest/api.html

解决方案 12:

从 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']

由 Techdragon 提供。请查看他的回答以了解更多详细信息:https://stackoverflow.com/a/45874251/1189659

解决方案 13:

对于第二级密钥检索,您可以执行以下操作:

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

解决方案 14:

一个可以包装字典并根据键检索的简单类:

class FindKey(dict):
    def get(self, path, default=None):
        keys = path.split(".")
        val = None

        for key in keys:
            if val:
                if isinstance(val, list):
                    val = [v.get(key, default) if v else None for v in val]
                else:
                    val = val.get(key, default)
            else:
                val = dict.get(self, key, default)

            if not val:
                break

        return val

例如:

person = {'person':{'name':{'first':'John'}}}
FindDict(person).get('person.name.first') # == 'John'

如果键不存在,则None默认返回。您可以使用包装器default=中的键覆盖它FindDict——例如:

FindDict(person, default='').get('person.name.last') # == doesn't exist, so ''

解决方案 15:

我非常简单地改编了 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)

解决方案 16:

在了解了如何深入获取属性后,我做了以下操作以dict使用点符号安全地获取嵌套值。这对我来说很有效,因为我的dicts是反序列化的 MongoDB 对象,所以我知道键名不包含.s。此外,在我的上下文中,我可以指定一个None我的数据中没有的虚假后备值 ( ),这样我就可以避免在调用函数时使用 try/except 模式。

from functools import reduce # Python 3
def deepgetitem(obj, item, fallback=None):
    """Steps through an item chain to get the ultimate value.

    If ultimate value or path to value does not exist, does not raise
    an exception and instead returns `fallback`.

    >>> d = {'snl_final': {'about': {'_icsd': {'icsd_id': 1}}}}
    >>> deepgetitem(d, 'snl_final.about._icsd.icsd_id')
    1
    >>> deepgetitem(d, 'snl_final.about._sandbox.sbx_id')
    >>>
    """
    def getitem(obj, name):
        try:
            return obj[name]
        except (KeyError, TypeError):
            return fallback
    return reduce(getitem, item.split('.'), obj)

解决方案 17:

最简单的方法是不使用库或编写函数,对于少量快速使用,最简单的方法是根据get(..., {})需要多次使用该模式,例如:

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

解决方案 18:

我的版本:

def get_nested(dictionary: dict, key: str, default=None, sep: str = '.'):
    if sep in key:
        first_key, other_keys = key.split(sep, 1)
        return get_nested(dictionary.get(first_key, {}), other_keys, default)
    return dictionary.get(key, default)

使用示例:

get_nested(
    {'nest': {'nest2': 777}},
    key='nest.nest2'
)
# returns: 777

get_nested(
    {'abc': {}},
    key='abc.lalala'
)
# returns: None   # 'cause defaut=None

get_nested(
    {},
    key='tyty.nana.qwerty',
    default={}
)
# returns: {}

解决方案 19:

我发现 unutbu 答案的改编对我自己的代码很有用:

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

如果字典中没有该键,它会为 key1 生成一个字典条目,这样您就可以避免 KeyError。如果您像我一样想要最终得到一个包含该键配对的嵌套字典,这似乎是最简单的解决方案。

解决方案 20:

另一个用于相同目的的函数也返回一个布尔值来表示是否找到了键并处理一些意外错误。

'''
json : json to extract value from if exists
path : details.detail.first_name
            empty path represents root

returns a tuple (boolean, object)
        boolean : True if path exists, otherwise False
        object : the object if path exists otherwise None

'''
def get_json_value_at_path(json, path=None, default=None):

    if not bool(path):
        return True, json
    if type(json) is not dict :
        raise ValueError(f'json={json}, path={path} not supported, json must be a dict')
    if type(path) is not str and type(path) is not list:
        raise ValueError(f'path format {path} not supported, path can be a list of strings like [x,y,z] or a string like x.y.z')

    if type(path) is str:
        path = path.strip('.').split('.')
    key = path[0]
    if key in json.keys():
        return get_json_value_at_path(json[key], path[1:], default)
    else:
        return False, default

使用示例:

my_json = {'details' : {'first_name' : 'holla', 'last_name' : 'holla'}}
print(get_json_value_at_path(my_json, 'details.first_name', ''))
print(get_json_value_at_path(my_json, 'details.phone', ''))

(没错,“holla”)

(错误的, '')

解决方案 21:

已经有很多好的答案,但是我想出了一个名为 get 的函数,类似于 JavaScript 中的 lodash get,它也支持通过索引进入列表:

def get(value, keys, default_value = None):
'''
    Useful for reaching into nested JSON like data
    Inspired by JavaScript lodash get and Clojure get-in etc.
'''
  if value is None or keys is None:
      return None
  path = keys.split('.') if isinstance(keys, str) else keys
  result = value
  def valid_index(key):
      return re.match('^([1-9][0-9]*|[0-9])$', key) and int(key) >= 0
  def is_dict_like(v):
      return hasattr(v, '__getitem__') and hasattr(v, '__contains__')
  for key in path:
      if isinstance(result, list) and valid_index(key) and int(key) < len(result):
          result = result[int(key)] if int(key) < len(result) else None
      elif is_dict_like(result) and key in result:
          result = result[key]
      else:
          result = default_value
          break
  return result

def test_get():
  assert get(None, ['foo']) == None
  assert get({'foo': 1}, None) == None
  assert get(None, None) == None
  assert get({'foo': 1}, []) == {'foo': 1}
  assert get({'foo': 1}, ['foo']) == 1
  assert get({'foo': 1}, ['bar']) == None
  assert get({'foo': 1}, ['bar'], 'the default') == 'the default'
  assert get({'foo': {'bar': 'hello'}}, ['foo', 'bar']) == 'hello'
  assert get({'foo': {'bar': 'hello'}}, 'foo.bar') == 'hello'
  assert get({'foo': [{'bar': 'hello'}]}, 'foo.0.bar') == 'hello'
  assert get({'foo': [{'bar': 'hello'}]}, 'foo.1') == None
  assert get({'foo': [{'bar': 'hello'}]}, 'foo.1.bar') == None
  assert get(['foo', 'bar'], '1') == 'bar'
  assert get(['foo', 'bar'], '2') == None

解决方案 22:

以下是基于 unutbu 函数答案的解决方案,另外还添加了:

  1. python 命名准则

  2. 默认值作为参数

  3. 不使用 try,而只是检查键是否在对象上

def safe_get(dictionary, *keys, default=None):
    for key in keys:
        if key not in dictionary:
            return default
        dictionary = dictionary[key]
    return dictionary

解决方案 23:

因为如果其中一个键丢失则引发键错误是合理的做法,我们甚至可以不检查它并将其像那样单独获取:

def get_dict(d, kl):
  cur = d[kl[0]]
  return get_dict(cur, kl[1:]) if len(kl) > 1 else cur

解决方案 24:

对方法进行了一些改进,reduce使其可以与列表配合使用。还使用数据路径作为以点分隔的字符串,而不是数组。

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)

解决方案 25:

我使用过的解决方案与 double get 类似,但增加了使用 if else 逻辑避免 TypeError 的功能:

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

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

解决方案 26:

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

pip 安装 dictor

字典对象

{
    "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"
            ]
        }
    }
}

要获取 Lonestar 的物品,只需提供一个以点分隔的路径,即

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

解决方案 27:

我稍微修改了这个答案。我添加了检查是否使用带数字的列表。所以现在我们可以以任何方式使用它。deep_get(allTemp, [0], {})或者deep_get(getMinimalTemp, [0, minimalTemperatureKey], 26)等等

def deep_get(_dict, keys, default=None):
    def _reducer(d, key):
        if isinstance(d, dict):
            return d.get(key, default)
        if isinstance(d, list):
            return d[key] if len(d) > 0 else default
        return default
    return reduce(_reducer, keys, _dict)

解决方案 28:

递归方法(мб пригодится)

示例字典:

foo = [{'feature_name': 'Sample Creator > Contract Details > Elements of the page',
  'scenarios': [{'scenario_name': 'SC, CD, Elements of the page',
                 'scenario_status': 'failed',
                 'scenario_tags': None,
                 'steps': [{'duration': 0,
                            'name': 'I open application Stage and login by '
                                    'SPT_LOGIN and password SPT_PWD',
                            'status': 'untested'},
                           {'duration': 0,
                            'name': 'I open Sample Creator query page',
                            'status': 'untested'},
                           {'duration': 7.78166389465332,
                            'name': 'I open application Stage and login by '
                                    'SPT_LOGIN and password SPT_PWD',
                            'status': 'passed'},
                           {'duration': 3.985326051712036,
                            'name': 'I open Sample Creator query page',
                            'status': 'passed'},
                           {'duration': 2.9063704013824463,
                            'name': 'Enter value: '
                                    'X-2008-CON-007,X-2011-CON-016 in '
                                    'textarea: project_text_area sleep: 1',
                            'status': 'passed'},
                           {'duration': 4.4447715282440186,
                            'name': 'I press on GET DATA',
                            'status': 'passed'},
                           {'duration': 1.1209557056427002,
                            'name': 'Verify the top table on Contract Details',
                            'status': 'passed'},
                           {'duration': 3.8173601627349854,
                            'name': 'I export contract_details table by offset '
                                    'x:100, y:150',
                            'status': 'passed'},
                           {'duration': 1.032956600189209,
                            'name': 'Check data of '
                                    'sc__cd_elements_of_the_page_1 and skip '
                                    'cols None',
                            'status': 'passed'},
                           {'duration': 0.04593634605407715,
                            'name': "Verify 'Number of Substances' column "
                                    'values',
                            'status': 'passed'},
                           {'duration': 0.10199904441833496,
                            'name': 'Substance Sample Details bottom table '
                                    'columns',
                            'status': 'passed'},
                           {'duration': 0.0009999275207519531,
                            'name': 'Verify the Substance Sample Details '
                                    'bottom table',
                            'status': 'passed'},
                           {'duration': 3.8558616638183594,
                            'name': 'I export substance_sample_details table '
                                    'by offset x:100, y:150',
                            'status': 'passed'},
                           {'duration': 1.0329277515411377,
                            'name': 'Check data of '
                                    'sc__cd_elements_of_the_page_2 and skip '
                                    'cols None',
                            'status': 'passed'},
                           {'duration': 0.2879970073699951,
                            'name': 'Click on AG-13369',
                            'status': 'passed'},
                           {'duration': 3.800830364227295,
                            'name': 'I export substance_sample_details table '
                                    'by offset x:100, y:150',
                            'status': 'passed'},
                           {'duration': 1.0169551372528076,
                            'name': 'Check data of '
                                    'sc__cd_elements_of_the_page_3 and skip '
                                    'cols None',
                            'status': 'passed'},
                           {'duration': 1.7484464645385742,
                            'name': 'Select all cells, table: 2',
                            'status': 'passed'},
                           {'duration': 3.812828779220581,
                            'name': 'I export substance_sample_details table '
                                    'by offset x:100, y:150',
                            'status': 'passed'},
                           {'duration': 1.0029594898223877,
                            'name': 'Check data of '
                                    'sc__cd_elements_of_the_page_2 and skip '
                                    'cols None',
                            'status': 'passed'},
                           {'duration': 1.6729373931884766,
                            'name': 'Set window size x:800, y:600',
                            'status': 'passed'},
                           {'duration': 30.145705699920654,
                            'name': 'All scrollers are placed on top 6 and far '
                                    'left 8',
                            'status': 'failed'}]}]},
  {'feature_name': 'Sample Creator > Substance Sample History > Elements of the '
                  'page',
  'scenarios': [{'scenario_name': 'SC, SSH, Elements of the page',
                 'scenario_status': 'passed',
                 'scenario_tags': None,
                 'steps': [{'duration': 0,
                            'name': 'I open application Stage and login by '
                                    'SPT_LOGIN and password SPT_PWD',
                            'status': 'untested'},
                           {'duration': 0,
                            'name': 'I open Sample Creator query page',
                            'status': 'untested'},
                           {'duration': 7.305850505828857,
                            'name': 'I open application Stage and login by '
                                    'SPT_LOGIN and password SPT_PWD',
                            'status': 'passed'},
                           {'duration': 3.500955104827881,
                            'name': 'I open Sample Creator query page',
                            'status': 'passed'},
                           {'duration': 3.0419492721557617,
                            'name': 'Enter value: NOA401800 SYN-NOA '
                                    'A,S4A482070C SYN-ISN-OLD '
                                    'O,S04A482167T,S04A482190Y,CSAA796564,CSCD106701 '
                                    'in textarea: id_text_area sleep: 1',
                            'status': 'passed'},
                           {'duration': 49.567158460617065,
                            'name': 'I press on GET DATA',
                            'status': 'passed'},
                           {'duration': 0.13904356956481934,
                            'name': 'Open substance_sample_history',
                            'status': 'passed'},
                           {'duration': 1.1039845943450928,
                            'name': 'Columns displayed',
                            'status': 'passed'},
                           {'duration': 3.881945848464966,
                            'name': 'I export export_parent_table table by '
                                    'offset x:100, y:150',
                            'status': 'passed'},
                           {'duration': 1.0334820747375488,
                            'name': 'Check data of '
                                    'sc__ssh_elements_of_the_page_1 and skip '
                                    'cols None',
                            'status': 'passed'},
                           {'duration': 0.0319981575012207,
                            'name': "Title is 'Additional Details for Marked "
                                    "Rows'",
                            'status': 'passed'},
                           {'duration': 0.08897256851196289,
                            'name': 'Columns displayed (the same as in top '
                                    'table)',
                            'status': 'passed'},
                           {'duration': 25.192569971084595,
                            'name': 'Verify the content of the bottom table',
                            'status': 'passed'},
                           {'duration': 4.308935880661011,
                            'name': 'I export '
                                    'additional_details_for_marked_rows table '
                                    'by offset x:100, y:150',
                            'status': 'passed'},
                           {'duration': 1.0089836120605469,
                            'name': 'Check data of '
                                    'sc__ssh_elements_of_the_page_1 and skip '
                                    'cols None',
                            'status': 'passed'}]}]}]

代码:

def get_keys(_dict: dict, prefix: list):
    prefix += list(_dict.keys())
    return prefix


def _loop_elements(elems:list, prefix=None, limit=None):
    prefix = prefix or []
    limit = limit or 9
    try:
        if len(elems) != 0 and isinstance(elems, list):
            for _ in elems:
                if isinstance(_, dict):
                    get_keys(_, prefix)
                    for item in _.values():
                        _loop_elements(item, prefix, limit)
        return prefix[:limit]
    except TypeError:
        return


>>>goo = _loop_elements(foo,limit=9)
>>>goo
['feature_name', 'scenarios', 'scenario_name', 'scenario_status', 'scenario_tags', 'steps', 'duration', 'name', 'status']

解决方案 29:

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

解决方案 30:

我已经编写了一个包 deepextract,它可以完全满足您的要求:https ://github.com/ya332/deepextract
您可以这样做

from deepextract import deepextract
# Demo: deepextract.extract_key(obj, key)
deeply_nested_dict = {
    "items": {
        "item": {
            "id": {
                "type": {
                    "donut": {
                        "name": {
                            "batters": {
                                "my_target_key": "my_target_value"
                            }
                        }
                    }
                }
            }
        }
    }
}
print(deepextract.extract_key(deeply_nested_dict, "my_target_key") == "my_target_value")

返回

True
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用