Python 检查dict键以确保所需的键始终存在,并且dict在定义的一组名称之外没有其他键名称
我有一个python的dict,它遵循以下通用格式:Python 检查dict键以确保所需的键始终存在,并且dict在定义的一组名称之外没有其他键名称,python,dictionary,Python,Dictionary,我有一个python的dict,它遵循以下通用格式: {'field': ['$.name'], 'group': 'name', 'function': 'some_function'} 我想对dict做一些预检查,以确保“field”始终存在,并且除了“group”和“function”之外没有其他键存在,这两个键都是可选的 我知道我可以通过使用一个长而不整洁的if语句来做到这一点,但我想一定有一个更干净的方法 这就是我目前拥有的: if(('field'在dict_name和len(di
{'field': ['$.name'], 'group': 'name', 'function': 'some_function'}
我想对dict做一些预检查,以确保“field”始终存在,并且除了“group”和“function”之外没有其他键存在,这两个键都是可选的
我知道我可以通过使用一个长而不整洁的if语句来做到这一点,但我想一定有一个更干净的方法
这就是我目前拥有的:
if(('field'在dict_name和len(dict_name.keys())==1)或
(“组”在dict_name和len中(dict_name.keys())==2)或
(“函数”在dict_name和len中(dict_name.keys())==2)或
(dict_name中的'group'和dict_name和len中的'function'(dict_name.keys())==3))
本质上,我首先检查“字段”是否存在,因为这是必需的。然后我检查它是否是唯一的键(这很好),或者它是“组”旁边的键而不是其他键,或者是“功能”旁边的键而不是其他键,或者是“组”和“功能”旁边的键而不是其他键
是否有更整洁的方法检查提供的钥匙只有这3把钥匙,其中两把是可选的?您可以使用
设置允许的钥匙,并使用内置功能检查dict的钥匙:
allowed_key={'field','group','function'}
如果d中有“字段”和“全部”(输入d中允许的\u键):
通过
这实际上相当于集合的方法:
测试集合中的每个元素是否在其他元素中
因此,通过将dict的键强制转换到一个集合并检查它们是否是允许的键的子集,这可以变得更加紧凑:
allowed_key={'field','group','function'}
如果d中有“字段”并设置(d)。IsubSet(允许的\u键):
通过
就我而言,您想检查一下
集合{'field'}
始终包含在dict键集合中
dict密钥集始终包含在集合{'field','group','function'}
所以只需编写代码
required_fields = {'field'}
allowed_fields = required_fields | {'group', 'function'}
d = {'field': 123} # Set any value here
if required_fields <= d.keys() <= allowed_fields:
print("Yes!")
else:
print("No!")
required_fields={'field'}
允许的_字段=必需的_字段|{'group','function'}
d={'field':123}#在此处设置任何值
如果需要,_fields返回一个原始数据支持的集。您可以利用这一点编写一个非常简洁的测试:
allowed = {'field', 'group', 'function'}
if 'field' in dict_name and dict_name.keys() <= allowed:
...
除了可读性之外,在某些情况下使用keys视图时,使用运算符是唯一可能的。例如,以下操作无法运行:
dict_name.keys().issubset(allowed)
但以下方法效果很好:
dict_name.keys() <= allowed
但这可能会将dict_name.keys()
包装到一个不必要的set
对象中。同时,
allowed >= dict_name.keys()
将实际翻转运算符并使用您还可以使用验证包,如模式
是的,通过将您的dict转换为:
从输入导入列表,可选
从数据类导入数据类
@数据类
类别MyDataclass:
字段:列表[str]
组:可选[str]=无
函数:可选[str]=None
结果=MyDataclass([“$.name”],“name”,“some_函数”)
#或者,相当于:
结果=MyDataclass(字段=[“$.name”],group=“name”,function=“some_function”)
#使用result.field、result.group、result.function访问
要直接回答您的问题,您可以编写以下内容,当输入字典中缺少字段时,它将引发异常:
dict_name={'field':['$.name'],'group':'name','function':'some_function'}
MyDataclass(*dict_名称)
请注意,由于使用了splat操作符,上述操作仅在键为字符串时有效。(*
)
转换为数据类后,您可以安全地使用它,并确保它具有字段。这不太容易出错,因为它可以防止在代码的不同部分混淆检查缺失参数的dict和未检查的dict。请参阅,以获取从理论角度的完整解释
数据类是Python中的惯用方式,类似于对象(字典)是JavaScript中的惯用方式。此外,如果您使用的IDE支持mypy/pyer/pep484,那么您将获得对象的类型提示由于PEP 484的双向性,这意味着如果您创建了一个缺少字段的dict,并将其传递给一个将其转换为数据类的函数,则类型检查器可能能够检查错误。
您可以使用将数据类转换回dict
另一个选项是namedtuple。不错!我在解释器中玩了一会儿,得到了d.keys()
上issubset
的属性错误。但我不知道你可以使用显式运算符。感谢你的教育:)联盟可能不会超过三个要素。实际上,3应该是len(允许)
。这确保了dict_name.keys()
不会引入任何新的elements@Kolay.Ne我想你需要像这样用set
包装d.keys()
:set(d.keys())
?@CristianGutu这是不必要的,dict.keys
返回一个类似set的视图对象。@CristianGutu,是的,这就是我的代码以前的样子。请查看我的答案版本的历史,以便更好地了解发生了什么变化,您很可能会理解为什么(更正我以前的评论)@CristianGutu实际上可能有一个很好的理由去做set(d)
,而不是d.keys()
:效率。有了这里代码中的数据,我认为{'group':'name','function':'func'}
将根据您的第二行(和第三行)传递必填字段得到了约400 ns。您是对的,我没有注意到,正如我所知,必须有更好的解决方案DataClass是Python 3.7中的新功能,为任何人wondering@AaronF我们现在无法控制的大多数系统至少都有Python3.6。当您完成开发时,大多数系统可能已经有了Python3.7
dict_name.keys().issubset(allowed)
dict_name.keys() <= allowed
allowed.issuperset(dict_name.keys())
allowed >= dict_name.keys()
from schema import Schema, And
my_schema = Schema({
'field': And(str, len),
'group': And(str, len),
'function': And(str, len)
})
data = {
'field': 'Hello',
'group': 'This is a group',
'function': 'some_function'
}
my_schema.validate(data)