2013-04-24 58 views
8

我想在字典中測試一個鍵的存在,因爲'if key is not in dictionary:do something' 我已經多次完成這個操作,但是這次它的行爲很奇怪。python 2.7在字典中的存在

特別:

termCircuit = termCircuitMap[term] 

回報KeyError異常

,當我在Eclipse中的PyDev調試這個代碼,我得到了以下(使用表達式):

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

不要任何人知道這是怎麼回事可能?我認爲,如果某個關鍵詞是'in',那麼它就在'字典'中。

我附上評估的屏幕截圖。

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

非常感謝解釋:)

+1

這很奇怪......這兩個條件語句之間是否存在任何代碼? – 2013-04-24 19:02:39

+1

如果您實際上連續運行這兩行,則不會解釋錯誤。 'aDict'中的key實際上比aDict.keys()中的'key快,優於'鍵,但它們都應該返回相同的值。是否有可能在這些檢查之間修改了字典? – 2013-04-24 19:02:42

+9

你能展示一個演示問題的實際代碼的例子嗎?字典中的鍵的類型是什麼?如果密鑰是具有不兼容的散列/相等定義的對象,則這種行爲是可能的。 – BrenBarn 2013-04-24 19:03:07

回答

11

您可能會看到,如果你的關鍵的__hash__功能沒有正確定義這種行爲。例如,下面給出大致爲您所描述的相同的行爲:

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 

在這種情況下,我產生隨機哈希值,這顯然是一個壞主意。如果你的關鍵值是可變的,那麼一個不太明顯的問題會產生相同的效果。 (通常,可變值不應該定義爲__hash__,並且不應該用作字典中的鍵)。

+2

Gah!花了太長時間寫同樣的東西。我只能添加一個指向'__hash__'方法規則的鏈接:http://docs.python.org/2/reference/datamodel.html#object.__hash__ – 2013-04-24 19:26:38

+0

謝謝,顯然問題在於我認爲對象是不可改變的,但它們不是。所以這裏是解釋如何發生這種情況,如果有人很好奇: o = SomeClass()#錯誤地認爲是不可變的 – jlanik 2013-04-25 12:27:03

+0

好吧,對不起,我很愚蠢地把代碼放在評論中,顯然。 因此,這裏的例子: O = SomeClass的() 地圖[O] =無 #now散列(O)== X 發生變異(O) #now散列(O)==Ý ○在地圖#prints False,因爲o的哈希是x,所以在map.keys()中添加 o #prints True,因爲map.keys()是一個列表,並且列表中的存在不會通過計算哈希來檢查(i猜...) – jlanik 2013-04-25 12:33:51