2013-04-24 15 views
8

Chcę przetestować obecność klucza w słowniku jako "jeśli klucz nie znajduje się w słowniku: zrób coś" Już zrobiłem to już wiele razy, ale tym razem zachowuje się dziwnie.python 2.7 obecność w słowniku

szczególnie:

termCircuit = termCircuitMap[term] 

powraca KeyError

kiedy debugowania tego kodu w Eclipse PyDev, mam następujący (przy użyciu wyrażeń):

term in termCircutiMap  # prints False 
term in termCircuitMap.keys() # prints True 

Czy ktoś zrozumieć, jak to jest możliwy? Pomyślałem, że jeśli coś jest "w" zestawie kluczy, to jest "w" słowniku.

Załączam zrzut ekranu oceny.

http://img836.imageshack.us/img836/1274/screenshotpython.png

dziękuję za wyjaśnienie :)

+1

to jest dziwne ... czy istnieje jakiś kod pomiędzy tymi dwoma instrukcjami warunkowymi? –

+1

Jeśli faktycznie uruchamiasz te dwie linie bezpośrednio po sobie, nie ma żadnego wyjaśnienia błędu. 'klucz w aDict' jest w rzeczywistości szybszy i lepszy od' key in aDict.keys() ', ale _długo_ obie zwracają tę samą wartość. Czy jest możliwe, że coś zmieniło słownik pomiędzy tymi kontrolami? –

+9

Czy możesz pokazać przykład rzeczywistego kodu, który demonstruje problem? Jaki jest typ kluczy w twoim dyktacie? Takie zachowanie może być możliwe, jeśli klucze są obiektami z niezgodnymi hasłami/definicjami równości. – BrenBarn

Odpowiedz

11

Możecie zobaczyć to zachowanie Jeśli klucz jest __hash__ funkcja nie jest poprawnie zdefiniowany. Na przykład, co następuje daje mniej więcej takie samo zachowanie jak opisywać:

import random 

class Evil(int): 
    def __hash__(self): 
     return random.randint(0, 10000) 

evil_vals = [Evil(n) for n in range(10)] 

dict_with_evil_keys = dict((evil_val, None) 
          for evil_val in evil_vals) 

print evil_vals[0] in dict_with_evil_keys # prints False 
print evil_vals[0] in dict_with_evil_keys.keys() # prints True 

W tym przypadku, jestem generowania losowych wartości hash, który jest oczywiście zły pomysł. Mniej oczywisty problem, który miałby ten sam skutek, może być, jeśli twoje kluczowe wartości są zmienne. (Ogólnie zmienne wartości nigdy nie powinny definiować __hash__ i nie powinny być przydatne jako klucze w słownikach.)

+2

Gah! Zbyt długo zajęło mi napisanie tego samego. Jedyne, co mogę dodać, to link do zasad dla metody "__hash__": http://docs.python.org/2/reference/datamodel.html#object.__hash__ –

+0

Dziękuję, najwyraźniej problem polegał na tym, że myślałem że obiekty są niezmienne, ale nie były.Oto wyjaśnienie, jak może się dziać ta sytuacja, jeśli ktoś jest ciekawy: o = SomeClass() # źle ma być niezmienny – jlanik

+0

Ok, przepraszam, jestem głupi, aby umieścić kod w komentarzach, podobno. Oto więc na przykład: O = SomeClass() mapę [O] = nie #now mieszania (O) == x mutacji (O) #now mieszania (O) O == r na mapie #prints Fałsz, ponieważ mieszadło o było x gdy zostało dodane o w map.keys() #prints Prawda, ponieważ map.keys() jest listą, a obecność na liście nie jest sprawdzana przez obliczanie skrótu (i domyślam się ...) – jlanik