loo*_*omi 53 python variables object
是否有更可读的方法来检查埋在dict中的密钥是否存在而不是单独检查每个级别?
假设我需要在埋藏的对象中获取此值(示例来自维基数据):
x = s['mainsnak']['datavalue']['value']['numeric-id']
Run Code Online (Sandbox Code Playgroud)
为了确保这不会以运行时错误结束,有必要检查每个级别,如下所示:
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']
Run Code Online (Sandbox Code Playgroud)
我能想到解决这个问题的另一种方法是将它包装成一个try catch构造,我觉得这个简单的任务也很尴尬.
我正在寻找类似的东西:
x = exists(s['mainsnak']['datavalue']['value']['numeric-id'])
Run Code Online (Sandbox Code Playgroud)
True如果所有级别都存在则返回
Aro*_*unt 90
简而言之,使用Python,您必须相信,请求宽恕比获得更容易
try:
x = s['mainsnak']['datavalue']['value']['numeric-id']
except KeyError:
pass
Run Code Online (Sandbox Code Playgroud)
这是我如何处理嵌套的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
Run Code Online (Sandbox Code Playgroud)
例:
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"))
Run Code Online (Sandbox Code Playgroud)
输出:
spam (exists): True
spam > bacon (do not exists): False
spam > egg (exists): True
spam > egg > bacon (exists): True
Run Code Online (Sandbox Code Playgroud)
它以给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)
Run Code Online (Sandbox Code Playgroud)
Dan*_*man 11
您可以使用.get默认值:
s.get('mainsnak', {}).get('datavalue', {}).get('value', {}).get('numeric-id')
Run Code Online (Sandbox Code Playgroud)
但这几乎肯定不如使用try/except.
dictionary = {
"main_key": {
"sub_key": "value",
},
}
if sub_key_value := dictionary.get("main_key", {}).get("sub_key"):
print(f"The key 'sub_key' exists in dictionary[main_key] and it's value is {sub_key_value}")
else:
print("Key 'sub_key' doesn't exists or their value is Falsy")
Run Code Online (Sandbox Code Playgroud)
一点但重要的澄清。
在前面的代码块中,我们验证字典中存在一个键,但它的值也是Truthy。大多数时候,这才是人们真正想要的,我认为这也是 OP 真正想要的。然而,这并不是最“正确”的答案,因为如果键存在但它的值为 False,上面的代码块会告诉我们键不存在,这是不正确的。
所以,我在这里给出一个更正确的答案:
dictionary = {
"main_key": {
"sub_key": False,
},
}
if "sub_key" in dictionary.get("main_key", {}):
print(f"The key 'sub_key' exists in dictionary[main_key] and it's value is {dictionary['main_key']['sub_key']}")
else:
print("Key 'sub_key' doesn't exists")
Run Code Online (Sandbox Code Playgroud)
尝试/例外似乎是最Python化的方法。
以下递归函数应该起作用(如果在dict中未找到其中一个键,则返回None):
def exists(obj, chain):
_key = chain.pop(0)
if _key in obj:
return exists(obj[_key], chain) if chain else obj[_key]
myDict ={
'mainsnak': {
'datavalue': {
'value': {
'numeric-id': 1
}
}
}
}
result = exists(myDict, ['mainsnak', 'datavalue', 'value', 'numeric-id'])
print(result)
>>> 1
Run Code Online (Sandbox Code Playgroud)
您可以使用pydash检查是否存在:http : //pydash.readthedocs.io/en/latest/api.html#pydash.objects.has
或获取值(您甚至可以设置默认值 - 如果不存在则返回):http : //pydash.readthedocs.io/en/latest/api.html#pydash.objects.has
下面是一个例子:
>>> get({'a': {'b': {'c': [1, 2, 3, 4]}}}, 'a.b.c[1]')
2
Run Code Online (Sandbox Code Playgroud)
我建议您使用python-benedict,一个具有完整键路径支持和许多实用方法的可靠 python dict 子类。
你只需要投射你现有的字典:
s = benedict(s)
Run Code Online (Sandbox Code Playgroud)
现在您的 dict 具有完整的 keypath 支持,您可以使用 in 运算符检查密钥是否以 pythonic 方式存在:
if 'mainsnak.datavalue.value.numeric-id' in s:
# do stuff
Run Code Online (Sandbox Code Playgroud)
这里是库存储库和文档:https : //github.com/fabiocaccamo/python-benedict
注意:我是这个项目的作者