Python 确定一个键是否存在于字典中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3733992/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:29:02  来源:igfitidea点击:

Determine whether a key is present in a dictionary

pythondictionary

提问by Avadhesh

Possible Duplicate:
'has_key()' or 'in'?

可能重复:
“has_key()”或“in”?

I have a Python dictionary like :

我有一个 Python 字典,如:

mydict = {'name':'abc','city':'xyz','country','def'}

I want to check if a key is in dictionary or not. I am eager to know that which is more preferable from the following two cases and why?

我想检查一个键是否在字典中。我很想知道以下两种情况哪个更可取,为什么?

1> if mydict.has_key('name'):
2> if 'name' in mydict:

采纳答案by Tim Pietzcker

if 'name' in mydict:

is the preferred, pythonic version. Use of has_key()is discouraged, and this method has been removed in Python 3.

是首选的pythonic版本。has_key()不鼓励使用,并且此方法已在 Python 3 中删除

回答by aaronasterling

In terms of bytecode, insaves a LOAD_ATTRand replaces a CALL_FUNCTIONwith a COMPARE_OP.

在字节码方面,in保存 aLOAD_ATTR并用 a 替换CALL_FUNCTIONa COMPARE_OP

>>> dis.dis(indict)
  2           0 LOAD_GLOBAL              0 (name)
              3 LOAD_GLOBAL              1 (d)
              6 COMPARE_OP               6 (in)
              9 POP_TOP             


>>> dis.dis(haskey)
  2           0 LOAD_GLOBAL              0 (d)
              3 LOAD_ATTR                1 (haskey)
              6 LOAD_GLOBAL              2 (name)
              9 CALL_FUNCTION            1
             12 POP_TOP             

My feelings are that inis muchmore readable and is to be preferred in every case that I can think of.

我的感觉是in很多更具可读性,是在任何情况下,我能想到的是首选。

In terms of performance, the timing reflects the opcode

在性能方面,时序反映了操作码

$ python -mtimeit -s'd = dict((i, i) for i in range(10000))' "'foo' in d"
 10000000 loops, best of 3: 0.11 usec per loop

$ python -mtimeit -s'd = dict((i, i) for i in range(10000))' "d.has_key('foo')"
  1000000 loops, best of 3: 0.205 usec per loop

inis almost twice as fast.

in几乎快两倍。

回答by martineau

My answer is "neither one".

我的回答是“都不是”。

I believe the most "Pythonic" way to do things is to NOT check beforehand if the key is in a dictionary and instead just write code that assumes it's there and catch any KeyErrors that get raised because it wasn't.

我相信最“Pythonic”的做事方式是不事先检查键是否在字典中,而只是编写假设它在那里的代码并捕获任何因为它不存在而引发的 KeyErrors。

This is usually done with enclosing the code in a try...exceptclause and is a well-known idiom usually expressed as "It's easier to ask forgiveness than permission" or with the acronym EAFP, which basically means it is better to try something and catch the errors instead for making sure everything's OK before doing anything. Why validate what doesn't need to be validated when you can handle exceptions gracefully instead of trying to avoid them? Because it's often more readable and the code tends to be faster if the probability is low that the key won't be there (or whatever preconditions there may be).

这通常是通过将代码包含在try...except子句中来完成的,这是一个众所周知的习语,通常表示为“请求宽恕比许可更容易”或首字母缩写词EAFP,这基本上意味着最好尝试一些事情并捕获错误在做任何事情之前确保一切正常。当您可以优雅地处理异常而不是试图避免它们时,为什么要验证不需要验证的内容?因为它通常更具可读性,并且如果密钥不存在的可能性很低(或可能存在的任何先决条件),则代码往往会更快。

Of course, this isn't appropriate in all situations and not everyone agrees with the philosophy, so you'll need to decide for yourself on a case-by-case basis. Not surprisingly the opposite of this is called LBYL for "Look Before You Leap".

当然,这并不适用于所有情况,也不是每个人都同意这一理念,因此您需要根据具体情况自行决定。毫不奇怪,与此相反的是 LBYL,意思是“Look Before You Leap”。

As a trivial example consider:

作为一个简单的例子,考虑:

if 'name' in dct:
    value = dct['name'] * 3
else:
    logerror('"%s" not found in dictionary, using default' % name)
    value = 42

vs

对比

try:
    value = dct['name'] * 3
except KeyError:
    logerror('"%s" not found in dictionary, using default' % name)
    value = 42

Although in the case it's almost exactly the same amount of code, the second doesn't spend time checking first and is probably slightly faster because of it (try...except block isn't totally free though, so it probably doesn't make that much difference here).

尽管在这种情况下,它的代码量几乎完全相同,但第二个不会先花时间检查,因此可能会稍微快一些(尝试...除了块不是完全免费的,所以它可能不会在这里产生很大的不同)。

Generally speaking, testing in advance can often be much more involved and the savings gain from not doing it can be significant. That said, if 'name' in dict:is better for the reasons stated in the other answers.

一般来说,提前测试通常会涉及更多,并且不这样做所带来的节省可能会很大。也就是说,if 'name' in dict:由于其他答案中所述的原因,效果更好。

If you're interested in the topic, this messagetitled "EAFP vs LBYL (was Re: A little disappointed so far)" from the Python mailing list archive probably explains the difference between the two approached better than I have here. There's also a good discussion about the two approaches in the book Python in a Nutshell, 2nd Edby Alex Martelli in chapter 6 on Exceptions titled Error-Checking Strategies. (I see there's now a newer 3rd edition, publish in 2017, which covers both Python 2.7 and 3.x).

如果你感兴趣的话题,这个消息标题为“ EAFP VS LBYL(为回复:到目前为止,有点失望)”从Python邮件列表归档或许可以解释两个走近之间的差别比我这里有。在Python in a Nutshell一书中,Alex Martelli 的第2 版中关于异常的第 6 章标题为错误检查策略,也对这两种方法进行了很好的讨论。(我看到现在有更新的第 3 版,于 2017 年发布,涵盖 Python 2.7 和 3.x)。

回答by Mike Graham

In the same vein as martineau's response, the best solution is often not to check. For example, the code

与马蒂诺的反应一样,最好的解决方案通常是不检查。例如,代码

if x in d:
    foo = d[x]
else:
    foo = bar

is normally written

通常写成

foo = d.get(x, bar)

which is shorter and more directly speaks to what you mean.

这是更短,更直接地说出你的意思。

Another common case is something like

另一个常见的情况是

if x not in d:
    d[x] = []

d[x].append(foo)

which can be rewritten

可以改写

d.setdefault(x, []).append(foo)

or rewritten even better by using a collections.defaultdict(list)for dand writing

或者使用collections.defaultdict(list)ford和 write 重写得更好

d[x].append(foo)