2015-09-20 8 views
5

myślę, że to jest bezpieczne:Czy sprawdzanie, czy klucz znajduje się w słowniku, a otrzymanie jego wartości w tym samym "jeśli" jest bezpieczne?

if key in test_dict: 
    if test_dict[key] == 'spam': 
     print('Spam detected!') 

ale jest to bezpieczne?

if key in test_dict and test_dict[key] == 'spam': 
    print('Spam detected!') 

To powinno zrobić to samo, ponieważ sprawdzanie kondycji jest leniwe w pytonie. Nie będzie próbował uzyskać wartości (i zgłosić wyjątek, ponieważ nie ma takiego klucza w dyktafonie), ponieważ pierwszy warunek nie jest już spełniony. Ale czy mogę polegać na leniwości i użyć drugiego przykładu w moich programach?

+3

tak, oba fragmenty są równoważne i "bezpieczne". –

Odpowiedz

13

Tak, to jest bezpieczne, Python będzie zwarcie jeśli wynik pierwszy wyraz w False, że czy nie oceniłoby drugiego wyrażenia w stanie if.

Ale lepszym sposobem na zrobienie tego jest użycie .get(), która zwraca None, jeśli klucz nie występuje w słowniku. Przykład -

if test_dict.get(key) == 'spam': 
    print('Spam detected!') 
+4

To nie jest odpowiednik - klucz spamu może mieć wartość "Brak". –

+1

W takim przypadku również jego odpowiednik nie spełniłby warunku. "Brak" nie jest równy spamowi. –

+0

@AnandSKumar A więc jedyna sytuacja, w której nie zadziałałaby, to kiedy szukam None? –

3

and test_dict[key] == 'spam': zostanie ocenione tylko jeśli if key in test_dict jest True, zachowa się dokładnie tak samo jak twój pierwszy kod, w którym masz zagnieżdżone.

Gdy używasz and, obie strony wyrażenia muszą być True, więc jeśli key in test_dict zwróci False, kod będzie zwarcie.

Używanie podejście and jest rzeczywiście najbardziej skuteczny zwłaszcza, gdy lewa strona wyrażenia jest fałsz:

In [13]: d = {k:k for k in range(10000)} 
In [14]: timeit 99999 in d and d[100] == "foo" 
10000000 loops, best of 3: 48.2 ns per loop 

In [15]: timeit d.get(9000) == "foo" 
10000000 loops, best of 3: 155 ns per loop 
In [16]: timeit 100 in d and d[100] == "foo 
10000000 loops, best of 3: 119 ns per loo  
In [17]: timeit d.get(100) == "foo" 
10000000 loops, best of 3: 141 ns per loop 
+0

Tak, ale bardziej wydajne jest po prostu 'd [100] ==" foo "' ale przy próbie z wyjątkiem zaokrąglić go. O ile większość kluczy nie znajduje się w dyktafonie. – strubbly

Powiązane problemy