2010-02-11 23 views
12

Qual è il modo più efficiente/più veloce/migliore per verificare se esiste una chiave?Python modo migliore per verificare la chiave esistente

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

O

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

Quali "efficienti", "più veloci" e "migliori" ti preoccupano veramente e quale definizione di "efficiente" e "migliore" hai in mente? –

+0

Immagino di voler dire qual è la migliore pratica di codifica. In questa particolare situazione, se 'subject' non è POST, che è un errore, non c'è un valore di default che dovrebbe esserci. Grazie per tutte le risposte. – mhost

risposta

28

Quest'ultimo (try/except) è generalmente la forma migliore.

try I blocchi sono molto economici ma la cattura di un'eccezione può essere più costosa. Un controllo di contenimento su un titolo tende ad essere economico, ma non più economico di niente. Sospetto che ci sarà un equilibrio di efficienza a seconda di quanto spesso lo 'subject' è davvero lì. Tuttavia, non importa, poiché l'ottimizzazione prematura è inutile, dispersiva, dispendiosa e inefficace. Andresti con la soluzione migliore.

Se il codice sarebbe in realtà essere di forma

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

allora quello che realmente vuole è request.POST.get('subject', some_default).

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

:)

+0

E se il valore associato a "" oggetto "' * è * 'Nessuno'? –

+2

Questo è meno leggibile rispetto a una delle soluzioni nel post originale. Sostituisce le eccezioni con il controllo del valore di ritorno ed è meno diretto di un controllo di contenimento, e ha un bug se 'request.Post ['subject']' è già 'None'. –

+1

@ Jon-Eric: Presumo che non può essere perché tutti i valori inviati HTTP sono stringhe. – recursive

1

Credo dipende se 'soggetto' non essere in POST è in realtà un'eccezione. Se non dovrebbe accadere, ma stai solo facendo attenzione, allora il tuo secondo metodo supporterà essere più efficiente e più veloce. Tuttavia, se si sta utilizzando l'assegno per fare 1 cosa o un'altra, non è opportuno utilizzare un'eccezione. Dall'aspetto del tuo codice, vorrei andare con la tua seconda opzione.

+0

È certamente una circostanza eccezionale (anche se si verifica il 90% delle volte!). –

+0

Come può accadere qualcosa che accade il 90% delle volte in modo eccezionale? –

+0

Tutti gli altri casi (la chiave esiste) si trovano in una categoria diversa da quella. –

2

Il secondo non funzionerà con collections.defaultdict e l'eccezione causerà un piccolo aumento di prestazioni. Oltre a ciò non c'è una vera differenza tra i due.

+3

È tecnicamente vero che il secondo metodo fallirà con 'collections.defaultdict', ma fondamentalmente, * questo è il motivo per cui *' collections.defaultdict' * esiste *. –

2

L'ultima volta che ho controllato, il primo è più veloce di pochi nanosecondi. Ma la maggior parte dei phythonistas sembra preferire la seconda.

penso io non sono l'unico che vuole riservare eccezioni per comportamento eccezionale, così cerco di utilizzare il primo, riservando la seconda quando è valida per non avere la chiave

+0

Questa * è * una circostanza eccezionale. –

1

Anche a me get() è possibile specificare un valore predefinito (diverso da none) nel caso in cui ciò abbia senso.

0

dict e molti oggetti dict-simile (tra cui Django di HttpRequest Sembra che tu stia usando) permettono il passaggio valore predefinito per get():

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

Questo è il metodo preferibile in quanto è il più breve e più trasparenti circa le vostre intenzioni .

4

I use .get() metodo - è il metodo preferibile.

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 
Problemi correlati