2011-09-26 66 views
9

__contains__文檔爲蟒蛇集意外行爲.__ contains__

print set.__contains__.__doc__ 
x.__contains__(y) <==> y in x. 

這似乎做工精細的基本對象,如int,即basestring等,但對於定義__ne__用戶定義的對象借款的文檔和__eq__方法,我得到意想不到的行爲。這裏是一個示例代碼:

class CA(object): 
    def __init__(self,name): 
    self.name = name 

    def __eq__(self,other): 
    if self.name == other.name: 
     return True 
    return False 

    def __ne__(self,other): 
    return not self.__eq__(other) 

obj1 = CA('hello') 
obj2 = CA('hello') 

theList = [obj1,] 
theSet = set(theList) 

# Test 1: list 
print (obj2 in theList) # return True 

# Test 2: set weird 
print (obj2 in theSet) # return False unexpected 

# Test 3: iterating over the set 
found = False 
for x in theSet: 
    if x == obj2: 
    found = True 

print found # return True 

# Test 4: Typcasting the set to a list 
print (obj2 in list(theSet)) # return True 

所以這是一個錯誤或功能?

+0

這個問題應該在這裏展示在stackoverflow:**如何提出問題**。明確點,用一個小例子來說明問題。正如其他人在這裏回答的,集合使用散列值,否則他們會得到列表的性能。 – bjarneh

+0

樣式注意:使用'return self.name == other.name'而不是'if cond:return True \ n return False' – jfs

回答

2

A set哈希值它是允許快速查找的元素。你必須覆蓋__hash__方法,這樣一個元素,可以發現:

class CA(object): 
    def __hash__(self): 
    return hash(self.name) 

列表不使用哈希,但每個元素比較喜歡你的for循環一樣。

3

這是因爲CA沒有實現__hash__

一個明智的實現是:

def __hash__(self): 
    return hash(self.name) 
7

對於set S和dicts,你需要定義__hash__。任何兩個相等的對象應該散列相同,以便在set s和dicts中獲得一致/預期的行爲。

我會建議使用_key方法,然後只是引用任何地方,你需要比較的項目的一部分,就像你叫__eq____neq__而不是重新實現它:

class CA(object): 
    def __init__(self,name): 
    self.name = name 

    def _key(self): 
    return type(self), self.name 

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

    def __eq__(self,other): 
    if self._key() == other._key(): 
     return True 
    return False 

    def __ne__(self,other): 
    return not self.__eq__(other)