2013-04-24 68 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