Python лучший способ проверить существующий ключ
Каков наиболее эффективный/быстрый/лучший способ проверки наличия ключа?
if 'subject' in request.POST:
subject = request.POST['subject']
else:
// handle error
ИЛИ
try:
subject = request.POST['subject']
except KeyError:
// handle error
Ответы
Ответ 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:
...
:)