2010-02-11 4 views
12

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

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

ИЛИ

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

Какой из «эффективных», «более быстрых» и «лучших» вам действительно интересен, и какое определение «эффективно» и «лучше» вы имеете в виду? –

+0

Я предполагаю, что я имел в виду, какая из лучших методик кодирования. В этой конкретной ситуации, если «субъект» не является POST, чем это ошибка, нет значения по умолчанию, которое должно быть там. Спасибо за все ответы. – mhost

ответ

28

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

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

Если код будет фактически формы

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

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

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

:)

+0

И если значение, связанное с '' subject ''*, равно' 'None'? –

+2

Это менее читаемо, чем любое из решений в исходном посте. Он заменяет исключения проверкой возвращаемого значения и менее прямой, чем проверка сдерживания, и имеет ошибку, если 'request.Post ['subject']' уже есть 'None'. –

+1

@ Jon-Eric: Я полагаю, этого не может быть, потому что все опубликованные по HTTP значения являются строками. – recursive

1

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

+0

Это, безусловно, исключительное обстоятельство (даже если оно происходит 90% времени!). –

+0

Как может быть что-то, что происходит 90% времени, исключительным? –

+0

Все остальные случаи (ключ существует) находятся в другой категории, чем он. –

2

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

+3

Технически верно, что второй метод завершится неудачей с 'collections.defaultdict', но более принципиально, поэтому *' collections.defaultdict' * существует *. –

2

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

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

+0

Это * * исключительное обстоятельство. –

1

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

0

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

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

Это preferrable метод, как это самый короткий и прозрачный о ваших намерениях ,

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 
Смежные вопросы