Python检查现有密钥的最佳方法

时间:2010-02-11 20:15:27

标签: python

检查密钥是否存在的效率更高/更快/更好?

if 'subject' in request.POST:
    subject = request.POST['subject']
else:
    // handle error

OR

try:
    subject = request.POST['subject']
except KeyError:
    // handle error

8 个答案:

答案 0 :(得分:35)

后者(try/except)形式通常是更好的形式。

try块非常便宜,但捕获异常可能更昂贵。对dict的收容检查往往便宜,但并不比没有便宜。我怀疑效率会取决于'subject'实际存在的频率。然而,这无所谓,因为过早的优化是无用的,分散注意力,浪费和无效。你会选择更好的解决方案。

如果代码实际上是

形式
if 'subject' in request.POST:
    subject = request.POST['subject']
else:
    subject = some_default

那么你真正想要的是request.POST.get('subject', some_default)

答案 1 :(得分:4)

我使用.get()方法 - 这是更好的方法。

Python 2.5.2 (r252:60911, Jul 22 2009, 15:33:10)
[GCC 4.2.4 (Ubuntu 4.2.4-1ubuntu3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import dis
>>> def f1(key, d):
...   if key in d:
...     return d[key]
...   else:
...     return "default"
...
>>> dis.dis(f1)
  2           0 LOAD_FAST                0 (key)
              3 LOAD_FAST                1 (d)
              6 COMPARE_OP               6 (in)
              9 JUMP_IF_FALSE           12 (to 24)
             12 POP_TOP

  3          13 LOAD_FAST                1 (d)
             16 LOAD_FAST                0 (key)
             19 BINARY_SUBSCR
             20 RETURN_VALUE
             21 JUMP_FORWARD             5 (to 29)
        >>   24 POP_TOP

  5          25 LOAD_CONST               1 ('default')
             28 RETURN_VALUE
        >>   29 LOAD_CONST               0 (None)
             32 RETURN_VALUE
>>> def f2(key, d):
...   return d.get(key, "default")
...
>>> dis.dis(f2)
  2           0 LOAD_FAST                1 (d)
              3 LOAD_ATTR                0 (get)
              6 LOAD_FAST                0 (key)
              9 LOAD_CONST               1 ('default')
             12 CALL_FUNCTION            2
             15 RETURN_VALUE
>>> def f3(key, d):
...   try:
...     return d[key]
...   except KeyError:
...     return "default"
...
>>> dis.dis(f3)
  2           0 SETUP_EXCEPT            12 (to 15)

  3           3 LOAD_FAST                1 (d)
              6 LOAD_FAST                0 (key)
              9 BINARY_SUBSCR
             10 RETURN_VALUE
             11 POP_BLOCK
             12 JUMP_FORWARD            23 (to 38)

  4     >>   15 DUP_TOP
             16 LOAD_GLOBAL              0 (KeyError)
             19 COMPARE_OP              10 (exception match)
             22 JUMP_IF_FALSE           11 (to 36)
             25 POP_TOP
             26 POP_TOP
             27 POP_TOP
             28 POP_TOP

  5          29 LOAD_CONST               1 ('default')
             32 RETURN_VALUE
             33 JUMP_FORWARD             2 (to 38)
        >>   36 POP_TOP
             37 END_FINALLY
        >>   38 LOAD_CONST               0 (None)
             41 RETURN_VALUE

答案 2 :(得分:2)

第二个将以collections.defaultdict失败,异常将导致性能下降。除此之外,两者之间没有真正的区别。

答案 3 :(得分:2)

上次检查时,第一次加快了几纳秒。但大多数的phythonistas似乎更喜欢第二个。

我认为我不是唯一一个想要为异常行为保留异常的人,所以我尝试使用第一个,当没有密钥时保留第二个

答案 4 :(得分:1)

我认为这取决于'主题'不在POST中是否实际上是一个例外。如果它不应该发生,但你只是要格外小心,那么我认为你的第二种方法会更高效,更快捷。但是,如果您使用检查做一件事或另一件事,则不适合使用例外。从代码的外观来看,我会选择第二个选项。

答案 5 :(得分:1)

我也喜欢get()你也可以在有意义的情况下指定一个默认值(非none)。

答案 6 :(得分:0)

dict和许多类似dict的对象(包括您似乎正在使用的Django的HttpRequest)允许将默认值传递给get()

subject = request.POST.get('subject', '[some_default_subject]')

这是首选方法,因为它是您最简单,最透明的。

答案 7 :(得分:-2)

subject = request.POST.get("subject")
if subject is None:
   ...

:)