2016-01-13 104 views
3

我與Python 2.7的一個問題最近:dict.keys()中的關鍵字與關鍵字有什麼區別?

class A(object): 
    def __init__(self, v): 
     self.v = v 

    def __eq__(self, other): 
     return self.v == other.v 

a1 = A(1) 
a2 = A(1) 

所以:

print a1 == a2 # True 

和:

d = {a1: 1} 
print a2 in d.keys() # True 

但是:

print a2 in d # False 

的問題是什麼的詞典定義。他與a2 ind.keys()a2 in d之間的主要區別?我怎樣才能得到a2 in d is True

回答

7

在Python 2.7中,dict.keys返回一個鍵列表,a2 in d.keys()將線性迭代所有鍵以查找a2是否在列表中。

a2 in d將只是做一個O(1)查找,基於對象a2的哈希值,在字典,看看是否關鍵a2d


但在你的情況下,問題是完全不同的。引用official documentation

如果一個類不定義__cmp__()__eq__()方法不應該限定__hash__()操作要麼; 如果它定義__cmp__()__eq__()但不__hash__(),它的實例將不會在散列集合可用。如果一個類定義了可變對象,並實現了__cmp__()__eq__()方法,它不應該實行__hash__(),因爲哈希的集合的實現需要一個對象的哈希值是不可變的(如果對象的散列值發生變化,這將是在錯誤的散列桶) 。

因爲我們還沒有明確定義__hash__功能,你破壞了他們和__hash__之間的合同將使用默認的基於對象的id,這將是雙方a1a2不同的散列。因此,即使a1a2是相似的,散列對象將它們視爲兩個不同的對象,因爲它們的哈希值是不同的。

要解決這個問題,你需要定義__hash__功能,這樣

class A(object): 

    def __init__(self, v): 
     self.v = v 

    def __eq__(self, other): 
     return self.v == other.v 

    def __hash__(self): 
     return hash(self.v) 

a1 = A(1) 
a2 = A(1) 

d = {a1: 1} 
print a2 in d.keys() # True 
print a2 in d   # True 
相關問題