Подтвердить что ты не робот

Python лучший способ проверить существующий ключ

Каков наиболее эффективный/быстрый/лучший способ проверки наличия ключа?

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

ИЛИ

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

Ответ 1

Последняя форма (try/except), как правило, является лучшей формой.

try блоки очень дешевы, но исключение может быть более дорогостоящим. Проверка сдерживания на дикте имеет тенденцию быть дешевой, но не дешевле, чем ничего. Я подозреваю, что будет баланс эффективности в зависимости от того, насколько часто 'subject' действительно существует. Однако это не имеет значения, поскольку преждевременная оптимизация бесполезна, отвлекает, расточительна и неэффективна. Вы бы выбрали лучшее решение.

Если бы код действительно имел вид

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

тогда вы действительно хотите request.POST.get('subject', some_default).

Ответ 2

Я использую метод .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

Ответ 3

Второе не будет выполнено с collections.defaultdict, и исключение вызовет небольшой балл производительности. Кроме того, между ними нет реальной разницы.

Ответ 4

В прошлый раз я проверил, первый - на несколько наносекунд быстрее. Но большинство phythonistas, похоже, предпочитают второй.

Я думаю, что я не единственный, кто хочет зарезервировать исключения для исключительного поведения, поэтому я пытаюсь использовать первый, сохраняя второй, когда он недействителен, чтобы не иметь ключ

Ответ 5

Я думаю, что это зависит от того, является ли "субъект" не в POST на самом деле исключением. Если это не должно произойти, но вы просто будьте осторожны, тогда ваш второй метод, я полагаю, будет более эффективным и быстрым. Однако, если вы используете чек, чтобы делать то же или что-то другое, нецелесообразно использовать исключение. Из внешнего вида вашего кода я бы воспользовался вторым вариантом.

Ответ 6

Мне тоже нравится get(), вы также можете указать значение по умолчанию (отличное от none), если это имеет смысл.

Ответ 7

dict и многие объекты типа dict (в том числе Django HttpRequest, которые вы, похоже, используете) позволяют передавать значение по умолчанию get():

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

Это предпочтительный метод, поскольку он является самым коротким и самым прозрачным в отношении ваших намерений.

Ответ 8

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

:)