我的字典看起来像
d = {
'name': 'name',
'date': 'date',
'amount': 'amount',
...
}
我想测试name
和amount
是否存在,所以我会做
if not `name` in d and not `amount` in d:
raise ValueError # for example
假设我从api获取数据,并且我想测试字典中是否存在10
字段。
它仍然是最好的寻找方式吗?
答案 0 :(得分:34)
您可以使用set
个交叉点:
if not d.viewkeys() & {'amount', 'name'}:
raise ValueError
在Python 3中,那就是:
if not d.keys() & {'amount', 'name'}:
raise ValueError
因为.keys()
默认返回dict视图。 .viewkeys()
(例如Python 3中的.keys()
返回的Dictionary view objects充当集合,交集测试非常有效。
Python 2.7中的演示:
>>> d = {
... 'name': 'name',
... 'date': 'date',
... 'amount': 'amount',
... }
>>> not d.viewkeys() & {'amount', 'name'}
False
>>> del d['name']
>>> not d.viewkeys() & {'amount', 'name'}
False
>>> del d['amount']
>>> not d.viewkeys() & {'amount', 'name'}
True
请注意,仅当缺少两个键时,此测试才会为True。如果在缺少的情况下需要通过测试,请使用:
if not d.viewkeys() >= {'amount', 'name'}:
raise ValueError
仅当两个键都存在时才为False:
>>> d = {
... 'name': 'name',
... 'date': 'date',
... 'amount': 'amount',
... }
>>> not d.viewkeys() >= {'amount', 'name'}
False
>>> del d['amount']
>>> not d.viewkeys() >= {'amount', 'name'})
True
对于严格比较(仅允许 两个键,不多也不少),在Python 2中,将字典视图与集合进行比较:
if d.viewkeys() != {'amount', 'name'}:
raise ValueError
(因此在Python 3中将是if d.keys() != {'amount', 'name'}
)。
答案 1 :(得分:9)
if all(k not in d for k in ('name', 'amount')):
raise ValueError
或
if all(k in d for k in ('name', 'amount')):
# do stuff
答案 2 :(得分:3)
你也可以使用set as:
>>> d = {
'name': 'name',
'date': 'date',
'amount': 'amount',
}
>>> test = set(['name','date'])
>>> test.issubset(set(d.keys()))
True
答案 3 :(得分:0)
我喜欢这种形式:
>>> d = {
... 'name': 'name',
... 'date': 'date',
... 'amount': 'amount'
... }
>>> tests={'name','date'}
>>> if any(test not in d for test in tests):
... raise ValueError
>>> # no error...
>>> del d['name']
>>> if any(test not in d for test in tests):
... raise ValueError
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError
适用于Py 2或Py 3
答案 4 :(得分:0)
为获得最大效率,您要避免构造不必要的临时set
(所有非比较二进制运算符都需要)。您可以这样做:
if name not in d and amount not in d:
具有:
if d.keys().isdisjoint(("amount", "name")):
,但这可能是错误的逻辑(在两种情况下),因为当缺少两个键时,它仅进入if
正文(并引发异常),并且您可能想如果缺少 键,则会引发异常。
有关拒绝d
(除非它同时包含两个键)的更可能的预期逻辑,您需要这样做:
if name not in d or amount not in d:
这可以通过以下方式通过设置操作来完成:
首先,您要预先定义(在函数外部,以避免重复构建集合):
required_keys = frozenset({"amount", "name"})
然后做:
if not d.keys() >= required_keys:
两个解决方案(isdisjoint
和>=
)都避免构造每个测试临时集,并且应尽可能高效地运行(一旦发现单个键丢失,则将其短路,并且仅两个键同时出现时,需要一对O(1)
查找)。就个人而言,对于两个键,我会坚持使用if name not in d or amount not in d:
,但是,如果键的数量增加,请确保使用类似集合的操作。