2010-02-11 22 views
12

Jaki jest skuteczniejszy/szybszy/lepszy sposób sprawdzenia, czy klucz istnieje?Python najlepszy sposób na sprawdzenie istniejącego klucza

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

LUB

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

Które z "skutecznych", "szybszych" i "lepszych" naprawdę Cię interesują i jaką masz na myśli definicję "wydajnego" i "lepszego"? –

+0

Chyba miałem na myśli, która jest najlepsza praktyka kodowania. W tej szczególnej sytuacji, jeśli "podmiot" nie jest POST, to jest to błąd, nie ma wartości domyślnej, która powinna tam być. Dziękuję za wszystkie odpowiedzi. – mhost

Odpowiedz

28

Ten ostatni (try/except) Formularz jest zazwyczaj lepszą formą.

bloki są bardzo tanie, ale złapanie wyjątku może być droższe. Kontrola powstrzymywania na dyktafonie wydaje się być tania, ale nie tańsza niż nic. Podejrzewam, że będzie równowaga wydajności w zależności od tego, jak często naprawdę jest tam 'subject'. Jednak to nie ma znaczenia, ponieważ przedwczesna optymalizacja jest bezużyteczna, rozprasza, marnuje i jest nieefektywna. Poszedłbyś z lepszym rozwiązaniem.

Jeśli kod byłby rzeczywiście formy

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

to co rzeczywiście chcesz to request.POST.get('subject', some_default).

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

:)

+0

A jeśli wartością związaną z '" subject "' * jest * 'None'? –

+2

Jest to mniej czytelne niż jedno z rozwiązań w oryginalnym poście. Zastępuje wyjątki sprawdzaniem wartości zwracanych i jest mniej bezpośredni niż sprawdzanie przechowalności, i ma błąd, jeśli 'request.Post ['subject']' jest już 'None'. –

+1

@ Jon-Eric: Zakładam, że nie może tak być, ponieważ wszystkie wartości zaksięgowane w protokole HTTP są ciągami. – recursive

1

myślę, że to zależy od tego, czy 'z zastrzeżeniem' nie będąc w POST jest rzeczywiście wyjątek. Jeśli nie powinno się tak stać, ale jesteś po prostu bardzo ostrożny, wtedy twoja druga metoda byłaby bardziej wydajna i szybsza. Jednak jeśli używasz sprawdzenia, aby wykonać jedną lub drugą czynność, nie należy używać wyjątku. Z wyglądu twojego kodu skorzystałbym z drugiej opcji.

+0

Jest to z pewnością wyjątkowa okoliczność (nawet jeśli występuje w 90% przypadków!). –

+0

Jak coś, co zdarza się w 90% przypadków, może być wyjątkowe? –

+0

Wszystkie pozostałe przypadki (klucz istnieje) należą do innej kategorii niż ta. –

2

Druga zakończy się niepowodzeniem z collections.defaultdict, a wyjątek spowoduje niewielki występ. Poza tym nie ma prawdziwej różnicy między tymi dwoma.

+3

Jest technicznie prawdą, że druga metoda zakończy się niepowodzeniem z 'collections.defaultdict', ale bardziej fundamentalnie, * dlatego * istnieje *' collections.defaultdict' * *. –

2

Ostatni raz, kiedy sprawdziłem, pierwszy jest o kilka nanosekund szybszy. Jednak większość phythonistas zdaje się faworyzować drugą.

myślę, że nie jestem jedynym, który chcesz zarezerwować wyjątki dla wyjątkowej zachowań, więc próbuję użyć pierwszego, zastrzegając drugi, gdy jest nieważny nie mieć klucz

+0

To * jest * wyjątkową okolicznością. –

1

Ja też lubię get() można również określić wartość domyślną (inną niż brak) w przypadku, gdy ma to sens.

0

dict i wiele dict-jak obiekty (w tym Django HttpRequest Wydaje się, że używając) umożliwiają przepuszczanie domyślną wartość get():

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

Jest to metoda preferuje, ponieważ jest to najkrótsza i najbardziej przejrzysty o swoich zamiarach .

4

Używam metody .get() - jest to metoda preferowana.

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 
Powiązane problemy